Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6:
PM / Hibernate: Fix preallocating of memory
PM / Hibernate: Remove swsusp.c finally
PM / Hibernate: Remove trailing space in message
PM: Allow SCSI devices to suspend/resume asynchronously
PM: Allow USB devices to suspend/resume asynchronously
USB: implement non-tree resume ordering constraints for PCI host controllers
PM: Allow PCI devices to suspend/resume asynchronously
PM / Hibernate: Swap, remove useless check from swsusp_read()
PM / Hibernate: Really deprecate deprecated user ioctls
PM: Allow device drivers to use dpm_wait()
PM: Start asynchronous resume threads upfront
PM: Add facility for advanced testing of async suspend/resume
PM: Add a switch for disabling/enabling asynchronous suspend/resume
PM: Asynchronous suspend and resume of devices
PM: Add parent information to timing messages
PM: Document device power attributes in sysfs
PM / Runtime: Add sysfs switch for disabling device run-time PM

+631 -84
+79
Documentation/ABI/testing/sysfs-devices-power
··· 1 + What: /sys/devices/.../power/ 2 + Date: January 2009 3 + Contact: Rafael J. Wysocki <rjw@sisk.pl> 4 + Description: 5 + The /sys/devices/.../power directory contains attributes 6 + allowing the user space to check and modify some power 7 + management related properties of given device. 8 + 9 + What: /sys/devices/.../power/wakeup 10 + Date: January 2009 11 + Contact: Rafael J. Wysocki <rjw@sisk.pl> 12 + Description: 13 + The /sys/devices/.../power/wakeup attribute allows the user 14 + space to check if the device is enabled to wake up the system 15 + from sleep states, such as the memory sleep state (suspend to 16 + RAM) and hibernation (suspend to disk), and to enable or disable 17 + it to do that as desired. 18 + 19 + Some devices support "wakeup" events, which are hardware signals 20 + used to activate the system from a sleep state. Such devices 21 + have one of the following two values for the sysfs power/wakeup 22 + file: 23 + 24 + + "enabled\n" to issue the events; 25 + + "disabled\n" not to do so; 26 + 27 + In that cases the user space can change the setting represented 28 + by the contents of this file by writing either "enabled", or 29 + "disabled" to it. 30 + 31 + For the devices that are not capable of generating system wakeup 32 + events this file contains "\n". In that cases the user space 33 + cannot modify the contents of this file and the device cannot be 34 + enabled to wake up the system. 35 + 36 + What: /sys/devices/.../power/control 37 + Date: January 2009 38 + Contact: Rafael J. Wysocki <rjw@sisk.pl> 39 + Description: 40 + The /sys/devices/.../power/control attribute allows the user 41 + space to control the run-time power management of the device. 42 + 43 + All devices have one of the following two values for the 44 + power/control file: 45 + 46 + + "auto\n" to allow the device to be power managed at run time; 47 + + "on\n" to prevent the device from being power managed; 48 + 49 + The default for all devices is "auto", which means that they may 50 + be subject to automatic power management, depending on their 51 + drivers. Changing this attribute to "on" prevents the driver 52 + from power managing the device at run time. Doing that while 53 + the device is suspended causes it to be woken up. 54 + 55 + What: /sys/devices/.../power/async 56 + Date: January 2009 57 + Contact: Rafael J. Wysocki <rjw@sisk.pl> 58 + Description: 59 + The /sys/devices/.../async attribute allows the user space to 60 + enable or diasble the device's suspend and resume callbacks to 61 + be executed asynchronously (ie. in separate threads, in parallel 62 + with the main suspend/resume thread) during system-wide power 63 + transitions (eg. suspend to RAM, hibernation). 64 + 65 + All devices have one of the following two values for the 66 + power/async file: 67 + 68 + + "enabled\n" to permit the asynchronous suspend/resume; 69 + + "disabled\n" to forbid it; 70 + 71 + The value of this attribute may be changed by writing either 72 + "enabled", or "disabled" to it. 73 + 74 + It generally is unsafe to permit the asynchronous suspend/resume 75 + of a device unless it is certain that all of the PM dependencies 76 + of the device are known to the PM core. However, for some 77 + devices this attribute is set to "enabled" by bus type code or 78 + device drivers and in that cases it should be safe to leave the 79 + default value.
+13
Documentation/ABI/testing/sysfs-power
··· 101 101 102 102 CAUTION: Using it will cause your machine's real-time (CMOS) 103 103 clock to be set to a random invalid time after a resume. 104 + 105 + What: /sys/power/pm_async 106 + Date: January 2009 107 + Contact: Rafael J. Wysocki <rjw@sisk.pl> 108 + Description: 109 + The /sys/power/pm_async file controls the switch allowing the 110 + user space to enable or disable asynchronous suspend and resume 111 + of devices. If enabled, this feature will cause some device 112 + drivers' suspend and resume callbacks to be executed in parallel 113 + with each other and with the main suspend thread. It is enabled 114 + if this file contains "1", which is the default. It may be 115 + disabled by writing "0" to this file, in which case all devices 116 + will be suspended and resumed synchronously.
+11
Documentation/feature-removal-schedule.txt
··· 64 64 65 65 --------------------------- 66 66 67 + What: Deprecated snapshot ioctls 68 + When: 2.6.36 69 + 70 + Why: The ioctls in kernel/power/user.c were marked as deprecated long time 71 + ago. Now they notify users about that so that they need to replace 72 + their userspace. After some more time, remove them completely. 73 + 74 + Who: Jiri Slaby <jirislaby@gmail.com> 75 + 76 + --------------------------- 77 + 67 78 What: The ieee80211_regdom module parameter 68 79 When: March 2010 / desktop catchup 69 80
+132 -11
drivers/base/power/main.c
··· 25 25 #include <linux/resume-trace.h> 26 26 #include <linux/interrupt.h> 27 27 #include <linux/sched.h> 28 + #include <linux/async.h> 28 29 29 30 #include "../base.h" 30 31 #include "power.h" ··· 43 42 LIST_HEAD(dpm_list); 44 43 45 44 static DEFINE_MUTEX(dpm_list_mtx); 45 + static pm_message_t pm_transition; 46 46 47 47 /* 48 48 * Set once the preparation of devices for a PM transition has started, reset ··· 58 56 void device_pm_init(struct device *dev) 59 57 { 60 58 dev->power.status = DPM_ON; 59 + init_completion(&dev->power.completion); 61 60 pm_runtime_init(dev); 62 61 } 63 62 ··· 114 111 pr_debug("PM: Removing info for %s:%s\n", 115 112 dev->bus ? dev->bus->name : "No Bus", 116 113 kobject_name(&dev->kobj)); 114 + complete_all(&dev->power.completion); 117 115 mutex_lock(&dpm_list_mtx); 118 116 list_del_init(&dev->power.entry); 119 117 mutex_unlock(&dpm_list_mtx); ··· 189 185 pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev), 190 186 error, (unsigned long long)ktime_to_ns(delta) >> 10); 191 187 } 188 + } 189 + 190 + /** 191 + * dpm_wait - Wait for a PM operation to complete. 192 + * @dev: Device to wait for. 193 + * @async: If unset, wait only if the device's power.async_suspend flag is set. 194 + */ 195 + static void dpm_wait(struct device *dev, bool async) 196 + { 197 + if (!dev) 198 + return; 199 + 200 + if (async || (pm_async_enabled && dev->power.async_suspend)) 201 + wait_for_completion(&dev->power.completion); 202 + } 203 + 204 + static int dpm_wait_fn(struct device *dev, void *async_ptr) 205 + { 206 + dpm_wait(dev, *((bool *)async_ptr)); 207 + return 0; 208 + } 209 + 210 + static void dpm_wait_for_children(struct device *dev, bool async) 211 + { 212 + device_for_each_child(dev, &async, dpm_wait_fn); 192 213 } 193 214 194 215 /** ··· 300 271 ktime_t calltime, delta, rettime; 301 272 302 273 if (initcall_debug) { 303 - pr_info("calling %s_i+ @ %i\n", 304 - dev_name(dev), task_pid_nr(current)); 274 + pr_info("calling %s+ @ %i, parent: %s\n", 275 + dev_name(dev), task_pid_nr(current), 276 + dev->parent ? dev_name(dev->parent) : "none"); 305 277 calltime = ktime_get(); 306 278 } 307 279 ··· 498 468 * device_resume - Execute "resume" callbacks for given device. 499 469 * @dev: Device to handle. 500 470 * @state: PM transition of the system being carried out. 471 + * @async: If true, the device is being resumed asynchronously. 501 472 */ 502 - static int device_resume(struct device *dev, pm_message_t state) 473 + static int device_resume(struct device *dev, pm_message_t state, bool async) 503 474 { 504 475 int error = 0; 505 476 506 477 TRACE_DEVICE(dev); 507 478 TRACE_RESUME(0); 508 479 480 + dpm_wait(dev->parent, async); 509 481 down(&dev->sem); 482 + 483 + dev->power.status = DPM_RESUMING; 510 484 511 485 if (dev->bus) { 512 486 if (dev->bus->pm) { ··· 544 510 } 545 511 End: 546 512 up(&dev->sem); 513 + complete_all(&dev->power.completion); 547 514 548 515 TRACE_RESUME(error); 549 516 return error; 517 + } 518 + 519 + static void async_resume(void *data, async_cookie_t cookie) 520 + { 521 + struct device *dev = (struct device *)data; 522 + int error; 523 + 524 + error = device_resume(dev, pm_transition, true); 525 + if (error) 526 + pm_dev_err(dev, pm_transition, " async", error); 527 + put_device(dev); 528 + } 529 + 530 + static bool is_async(struct device *dev) 531 + { 532 + return dev->power.async_suspend && pm_async_enabled 533 + && !pm_trace_is_enabled(); 550 534 } 551 535 552 536 /** ··· 577 525 static void dpm_resume(pm_message_t state) 578 526 { 579 527 struct list_head list; 528 + struct device *dev; 580 529 ktime_t starttime = ktime_get(); 581 530 582 531 INIT_LIST_HEAD(&list); 583 532 mutex_lock(&dpm_list_mtx); 584 - while (!list_empty(&dpm_list)) { 585 - struct device *dev = to_device(dpm_list.next); 533 + pm_transition = state; 586 534 535 + list_for_each_entry(dev, &dpm_list, power.entry) { 536 + if (dev->power.status < DPM_OFF) 537 + continue; 538 + 539 + INIT_COMPLETION(dev->power.completion); 540 + if (is_async(dev)) { 541 + get_device(dev); 542 + async_schedule(async_resume, dev); 543 + } 544 + } 545 + 546 + while (!list_empty(&dpm_list)) { 547 + dev = to_device(dpm_list.next); 587 548 get_device(dev); 588 - if (dev->power.status >= DPM_OFF) { 549 + if (dev->power.status >= DPM_OFF && !is_async(dev)) { 589 550 int error; 590 551 591 - dev->power.status = DPM_RESUMING; 592 552 mutex_unlock(&dpm_list_mtx); 593 553 594 - error = device_resume(dev, state); 554 + error = device_resume(dev, state, false); 595 555 596 556 mutex_lock(&dpm_list_mtx); 597 557 if (error) ··· 618 554 } 619 555 list_splice(&list, &dpm_list); 620 556 mutex_unlock(&dpm_list_mtx); 557 + async_synchronize_full(); 621 558 dpm_show_time(starttime, state, NULL); 622 559 } 623 560 ··· 796 731 return error; 797 732 } 798 733 734 + static int async_error; 735 + 799 736 /** 800 737 * device_suspend - Execute "suspend" callbacks for given device. 801 738 * @dev: Device to handle. 802 739 * @state: PM transition of the system being carried out. 740 + * @async: If true, the device is being suspended asynchronously. 803 741 */ 804 - static int device_suspend(struct device *dev, pm_message_t state) 742 + static int __device_suspend(struct device *dev, pm_message_t state, bool async) 805 743 { 806 744 int error = 0; 807 745 746 + dpm_wait_for_children(dev, async); 808 747 down(&dev->sem); 748 + 749 + if (async_error) 750 + goto End; 809 751 810 752 if (dev->class) { 811 753 if (dev->class->pm) { ··· 844 772 error = legacy_suspend(dev, state, dev->bus->suspend); 845 773 } 846 774 } 775 + 776 + if (!error) 777 + dev->power.status = DPM_OFF; 778 + 847 779 End: 848 780 up(&dev->sem); 781 + complete_all(&dev->power.completion); 849 782 850 783 return error; 784 + } 785 + 786 + static void async_suspend(void *data, async_cookie_t cookie) 787 + { 788 + struct device *dev = (struct device *)data; 789 + int error; 790 + 791 + error = __device_suspend(dev, pm_transition, true); 792 + if (error) { 793 + pm_dev_err(dev, pm_transition, " async", error); 794 + async_error = error; 795 + } 796 + 797 + put_device(dev); 798 + } 799 + 800 + static int device_suspend(struct device *dev) 801 + { 802 + INIT_COMPLETION(dev->power.completion); 803 + 804 + if (pm_async_enabled && dev->power.async_suspend) { 805 + get_device(dev); 806 + async_schedule(async_suspend, dev); 807 + return 0; 808 + } 809 + 810 + return __device_suspend(dev, pm_transition, false); 851 811 } 852 812 853 813 /** ··· 894 790 895 791 INIT_LIST_HEAD(&list); 896 792 mutex_lock(&dpm_list_mtx); 793 + pm_transition = state; 794 + async_error = 0; 897 795 while (!list_empty(&dpm_list)) { 898 796 struct device *dev = to_device(dpm_list.prev); 899 797 900 798 get_device(dev); 901 799 mutex_unlock(&dpm_list_mtx); 902 800 903 - error = device_suspend(dev, state); 801 + error = device_suspend(dev); 904 802 905 803 mutex_lock(&dpm_list_mtx); 906 804 if (error) { ··· 910 804 put_device(dev); 911 805 break; 912 806 } 913 - dev->power.status = DPM_OFF; 914 807 if (!list_empty(&dev->power.entry)) 915 808 list_move(&dev->power.entry, &list); 916 809 put_device(dev); 810 + if (async_error) 811 + break; 917 812 } 918 813 list_splice(&list, dpm_list.prev); 919 814 mutex_unlock(&dpm_list_mtx); 815 + async_synchronize_full(); 816 + if (!error) 817 + error = async_error; 920 818 if (!error) 921 819 dpm_show_time(starttime, state, NULL); 922 820 return error; ··· 1046 936 printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret); 1047 937 } 1048 938 EXPORT_SYMBOL_GPL(__suspend_report_result); 939 + 940 + /** 941 + * device_pm_wait_for_dev - Wait for suspend/resume of a device to complete. 942 + * @dev: Device to wait for. 943 + * @subordinate: Device that needs to wait for @dev. 944 + */ 945 + void device_pm_wait_for_dev(struct device *subordinate, struct device *dev) 946 + { 947 + dpm_wait(dev, subordinate->power.async_suspend); 948 + } 949 + EXPORT_SYMBOL_GPL(device_pm_wait_for_dev);
+3 -3
drivers/base/power/power.h
··· 12 12 13 13 #ifdef CONFIG_PM_SLEEP 14 14 15 - /* 16 - * main.c 17 - */ 15 + /* kernel/power/main.c */ 16 + extern int pm_async_enabled; 18 17 18 + /* drivers/base/power/main.c */ 19 19 extern struct list_head dpm_list; /* The active device list */ 20 20 21 21 static inline struct device *to_device(struct list_head *entry)
+45
drivers/base/power/runtime.c
··· 1011 1011 EXPORT_SYMBOL_GPL(pm_runtime_enable); 1012 1012 1013 1013 /** 1014 + * pm_runtime_forbid - Block run-time PM of a device. 1015 + * @dev: Device to handle. 1016 + * 1017 + * Increase the device's usage count and clear its power.runtime_auto flag, 1018 + * so that it cannot be suspended at run time until pm_runtime_allow() is called 1019 + * for it. 1020 + */ 1021 + void pm_runtime_forbid(struct device *dev) 1022 + { 1023 + spin_lock_irq(&dev->power.lock); 1024 + if (!dev->power.runtime_auto) 1025 + goto out; 1026 + 1027 + dev->power.runtime_auto = false; 1028 + atomic_inc(&dev->power.usage_count); 1029 + __pm_runtime_resume(dev, false); 1030 + 1031 + out: 1032 + spin_unlock_irq(&dev->power.lock); 1033 + } 1034 + EXPORT_SYMBOL_GPL(pm_runtime_forbid); 1035 + 1036 + /** 1037 + * pm_runtime_allow - Unblock run-time PM of a device. 1038 + * @dev: Device to handle. 1039 + * 1040 + * Decrease the device's usage count and set its power.runtime_auto flag. 1041 + */ 1042 + void pm_runtime_allow(struct device *dev) 1043 + { 1044 + spin_lock_irq(&dev->power.lock); 1045 + if (dev->power.runtime_auto) 1046 + goto out; 1047 + 1048 + dev->power.runtime_auto = true; 1049 + if (atomic_dec_and_test(&dev->power.usage_count)) 1050 + __pm_runtime_idle(dev); 1051 + 1052 + out: 1053 + spin_unlock_irq(&dev->power.lock); 1054 + } 1055 + EXPORT_SYMBOL_GPL(pm_runtime_allow); 1056 + 1057 + /** 1014 1058 * pm_runtime_init - Initialize run-time PM fields in given device object. 1015 1059 * @dev: Device object to initialize. 1016 1060 */ ··· 1072 1028 1073 1029 atomic_set(&dev->power.child_count, 0); 1074 1030 pm_suspend_ignore_children(dev, false); 1031 + dev->power.runtime_auto = true; 1075 1032 1076 1033 dev->power.request_pending = false; 1077 1034 dev->power.request = RPM_REQ_NONE;
+100
drivers/base/power/sysfs.c
··· 4 4 5 5 #include <linux/device.h> 6 6 #include <linux/string.h> 7 + #include <linux/pm_runtime.h> 7 8 #include "power.h" 8 9 9 10 /* 11 + * control - Report/change current runtime PM setting of the device 12 + * 13 + * Runtime power management of a device can be blocked with the help of 14 + * this attribute. All devices have one of the following two values for 15 + * the power/control file: 16 + * 17 + * + "auto\n" to allow the device to be power managed at run time; 18 + * + "on\n" to prevent the device from being power managed at run time; 19 + * 20 + * The default for all devices is "auto", which means that devices may be 21 + * subject to automatic power management, depending on their drivers. 22 + * Changing this attribute to "on" prevents the driver from power managing 23 + * the device at run time. Doing that while the device is suspended causes 24 + * it to be woken up. 25 + * 10 26 * wakeup - Report/change current wakeup option for device 11 27 * 12 28 * Some devices support "wakeup" events, which are hardware signals ··· 54 38 * wakeup events internally (unless they are disabled), keeping 55 39 * their hardware in low power modes whenever they're unused. This 56 40 * saves runtime power, without requiring system-wide sleep states. 41 + * 42 + * async - Report/change current async suspend setting for the device 43 + * 44 + * Asynchronous suspend and resume of the device during system-wide power 45 + * state transitions can be enabled by writing "enabled" to this file. 46 + * Analogously, if "disabled" is written to this file, the device will be 47 + * suspended and resumed synchronously. 48 + * 49 + * All devices have one of the following two values for power/async: 50 + * 51 + * + "enabled\n" to permit the asynchronous suspend/resume of the device; 52 + * + "disabled\n" to forbid it; 53 + * 54 + * NOTE: It generally is unsafe to permit the asynchronous suspend/resume 55 + * of a device unless it is certain that all of the PM dependencies of the 56 + * device are known to the PM core. However, for some devices this 57 + * attribute is set to "enabled" by bus type code or device drivers and in 58 + * that cases it should be safe to leave the default value. 57 59 */ 58 60 59 61 static const char enabled[] = "enabled"; 60 62 static const char disabled[] = "disabled"; 63 + 64 + #ifdef CONFIG_PM_RUNTIME 65 + static const char ctrl_auto[] = "auto"; 66 + static const char ctrl_on[] = "on"; 67 + 68 + static ssize_t control_show(struct device *dev, struct device_attribute *attr, 69 + char *buf) 70 + { 71 + return sprintf(buf, "%s\n", 72 + dev->power.runtime_auto ? ctrl_auto : ctrl_on); 73 + } 74 + 75 + static ssize_t control_store(struct device * dev, struct device_attribute *attr, 76 + const char * buf, size_t n) 77 + { 78 + char *cp; 79 + int len = n; 80 + 81 + cp = memchr(buf, '\n', n); 82 + if (cp) 83 + len = cp - buf; 84 + if (len == sizeof ctrl_auto - 1 && strncmp(buf, ctrl_auto, len) == 0) 85 + pm_runtime_allow(dev); 86 + else if (len == sizeof ctrl_on - 1 && strncmp(buf, ctrl_on, len) == 0) 87 + pm_runtime_forbid(dev); 88 + else 89 + return -EINVAL; 90 + return n; 91 + } 92 + 93 + static DEVICE_ATTR(control, 0644, control_show, control_store); 94 + #endif 61 95 62 96 static ssize_t 63 97 wake_show(struct device * dev, struct device_attribute *attr, char * buf) ··· 143 77 144 78 static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store); 145 79 80 + #ifdef CONFIG_PM_SLEEP_ADVANCED_DEBUG 81 + static ssize_t async_show(struct device *dev, struct device_attribute *attr, 82 + char *buf) 83 + { 84 + return sprintf(buf, "%s\n", 85 + device_async_suspend_enabled(dev) ? enabled : disabled); 86 + } 87 + 88 + static ssize_t async_store(struct device *dev, struct device_attribute *attr, 89 + const char *buf, size_t n) 90 + { 91 + char *cp; 92 + int len = n; 93 + 94 + cp = memchr(buf, '\n', n); 95 + if (cp) 96 + len = cp - buf; 97 + if (len == sizeof enabled - 1 && strncmp(buf, enabled, len) == 0) 98 + device_enable_async_suspend(dev); 99 + else if (len == sizeof disabled - 1 && strncmp(buf, disabled, len) == 0) 100 + device_disable_async_suspend(dev); 101 + else 102 + return -EINVAL; 103 + return n; 104 + } 105 + 106 + static DEVICE_ATTR(async, 0644, async_show, async_store); 107 + #endif /* CONFIG_PM_SLEEP_ADVANCED_DEBUG */ 146 108 147 109 static struct attribute * power_attrs[] = { 110 + #ifdef CONFIG_PM_RUNTIME 111 + &dev_attr_control.attr, 112 + #endif 148 113 &dev_attr_wakeup.attr, 114 + #ifdef CONFIG_PM_SLEEP_ADVANCED_DEBUG 115 + &dev_attr_async.attr, 116 + #endif 149 117 NULL, 150 118 }; 151 119 static struct attribute_group pm_attr_group = {
+1
drivers/pci/pci.c
··· 1540 1540 int pm; 1541 1541 u16 pmc; 1542 1542 1543 + device_enable_async_suspend(&dev->dev); 1543 1544 dev->wakeup_prepared = false; 1544 1545 dev->pm_cap = 0; 1545 1546
+1
drivers/pci/pcie/portdrv_core.c
··· 285 285 pci_name(pdev), 286 286 get_descriptor_id(pdev->pcie_type, service)); 287 287 device->parent = &pdev->dev; 288 + device_enable_async_suspend(device); 288 289 289 290 retval = device_register(device); 290 291 if (retval)
+1
drivers/pci/probe.c
··· 1436 1436 if (error) 1437 1437 goto dev_reg_err; 1438 1438 b->bridge = get_device(dev); 1439 + device_enable_async_suspend(b->bridge); 1439 1440 1440 1441 if (!parent) 1441 1442 set_dev_node(b->bridge, pcibus_to_node(b));
+4
drivers/scsi/hosts.c
··· 215 215 shost->shost_gendev.parent = dev ? dev : &platform_bus; 216 216 shost->dma_dev = dma_dev; 217 217 218 + device_enable_async_suspend(&shost->shost_gendev); 219 + 218 220 error = device_add(&shost->shost_gendev); 219 221 if (error) 220 222 goto out; 221 223 222 224 scsi_host_set_state(shost, SHOST_RUNNING); 223 225 get_device(shost->shost_gendev.parent); 226 + 227 + device_enable_async_suspend(&shost->shost_dev); 224 228 225 229 error = device_add(&shost->shost_dev); 226 230 if (error)
+4
drivers/scsi/scsi_sysfs.c
··· 847 847 if (starget->state != STARGET_CREATED) 848 848 return 0; 849 849 850 + device_enable_async_suspend(&starget->dev); 851 + 850 852 error = device_add(&starget->dev); 851 853 if (error) { 852 854 dev_err(&starget->dev, "target device_add failed, error %d\n", error); ··· 889 887 return error; 890 888 891 889 transport_configure_device(&starget->dev); 890 + device_enable_async_suspend(&sdev->sdev_gendev); 892 891 error = device_add(&sdev->sdev_gendev); 893 892 if (error) { 894 893 printk(KERN_INFO "error 1\n"); 895 894 return error; 896 895 } 896 + device_enable_async_suspend(&sdev->sdev_dev); 897 897 error = device_add(&sdev->sdev_dev); 898 898 if (error) { 899 899 printk(KERN_INFO "error 2\n");
+8
drivers/usb/core/driver.c
··· 1022 1022 goto done; 1023 1023 } 1024 1024 1025 + /* Non-root devices on a full/low-speed bus must wait for their 1026 + * companion high-speed root hub, in case a handoff is needed. 1027 + */ 1028 + if (!(msg.event & PM_EVENT_AUTO) && udev->parent && 1029 + udev->bus->hs_companion) 1030 + device_pm_wait_for_dev(&udev->dev, 1031 + &udev->bus->hs_companion->root_hub->dev); 1032 + 1025 1033 if (udev->quirks & USB_QUIRK_RESET_RESUME) 1026 1034 udev->reset_resume = 1; 1027 1035
+1
drivers/usb/core/endpoint.c
··· 186 186 ep_dev->dev.parent = parent; 187 187 ep_dev->dev.release = ep_device_release; 188 188 dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress); 189 + device_enable_async_suspend(&ep_dev->dev); 189 190 190 191 retval = device_register(&ep_dev->dev); 191 192 if (retval)
+126 -1
drivers/usb/core/hcd-pci.c
··· 19 19 #include <linux/kernel.h> 20 20 #include <linux/module.h> 21 21 #include <linux/pci.h> 22 + #include <linux/pm_runtime.h> 22 23 #include <linux/usb.h> 23 24 24 25 #include <asm/io.h> ··· 38 37 39 38 /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */ 40 39 40 + #ifdef CONFIG_PM_SLEEP 41 + 42 + /* Coordinate handoffs between EHCI and companion controllers 43 + * during system resume 44 + */ 45 + 46 + static DEFINE_MUTEX(companions_mutex); 47 + 48 + #define CL_UHCI PCI_CLASS_SERIAL_USB_UHCI 49 + #define CL_OHCI PCI_CLASS_SERIAL_USB_OHCI 50 + #define CL_EHCI PCI_CLASS_SERIAL_USB_EHCI 51 + 52 + enum companion_action { 53 + SET_HS_COMPANION, CLEAR_HS_COMPANION, WAIT_FOR_COMPANIONS 54 + }; 55 + 56 + static void companion_common(struct pci_dev *pdev, struct usb_hcd *hcd, 57 + enum companion_action action) 58 + { 59 + struct pci_dev *companion; 60 + struct usb_hcd *companion_hcd; 61 + unsigned int slot = PCI_SLOT(pdev->devfn); 62 + 63 + /* Iterate through other PCI functions in the same slot. 64 + * If pdev is OHCI or UHCI then we are looking for EHCI, and 65 + * vice versa. 66 + */ 67 + companion = NULL; 68 + for (;;) { 69 + companion = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, companion); 70 + if (!companion) 71 + break; 72 + if (companion->bus != pdev->bus || 73 + PCI_SLOT(companion->devfn) != slot) 74 + continue; 75 + 76 + companion_hcd = pci_get_drvdata(companion); 77 + if (!companion_hcd) 78 + continue; 79 + 80 + /* For SET_HS_COMPANION, store a pointer to the EHCI bus in 81 + * the OHCI/UHCI companion bus structure. 82 + * For CLEAR_HS_COMPANION, clear the pointer to the EHCI bus 83 + * in the OHCI/UHCI companion bus structure. 84 + * For WAIT_FOR_COMPANIONS, wait until the OHCI/UHCI 85 + * companion controllers have fully resumed. 86 + */ 87 + 88 + if ((pdev->class == CL_OHCI || pdev->class == CL_UHCI) && 89 + companion->class == CL_EHCI) { 90 + /* action must be SET_HS_COMPANION */ 91 + dev_dbg(&companion->dev, "HS companion for %s\n", 92 + dev_name(&pdev->dev)); 93 + hcd->self.hs_companion = &companion_hcd->self; 94 + 95 + } else if (pdev->class == CL_EHCI && 96 + (companion->class == CL_OHCI || 97 + companion->class == CL_UHCI)) { 98 + switch (action) { 99 + case SET_HS_COMPANION: 100 + dev_dbg(&pdev->dev, "HS companion for %s\n", 101 + dev_name(&companion->dev)); 102 + companion_hcd->self.hs_companion = &hcd->self; 103 + break; 104 + case CLEAR_HS_COMPANION: 105 + companion_hcd->self.hs_companion = NULL; 106 + break; 107 + case WAIT_FOR_COMPANIONS: 108 + device_pm_wait_for_dev(&pdev->dev, 109 + &companion->dev); 110 + break; 111 + } 112 + } 113 + } 114 + } 115 + 116 + static void set_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd) 117 + { 118 + mutex_lock(&companions_mutex); 119 + dev_set_drvdata(&pdev->dev, hcd); 120 + companion_common(pdev, hcd, SET_HS_COMPANION); 121 + mutex_unlock(&companions_mutex); 122 + } 123 + 124 + static void clear_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd) 125 + { 126 + mutex_lock(&companions_mutex); 127 + dev_set_drvdata(&pdev->dev, NULL); 128 + 129 + /* If pdev is OHCI or UHCI, just clear its hs_companion pointer */ 130 + if (pdev->class == CL_OHCI || pdev->class == CL_UHCI) 131 + hcd->self.hs_companion = NULL; 132 + 133 + /* Otherwise search for companion buses and clear their pointers */ 134 + else 135 + companion_common(pdev, hcd, CLEAR_HS_COMPANION); 136 + mutex_unlock(&companions_mutex); 137 + } 138 + 139 + static void wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd) 140 + { 141 + /* Only EHCI controllers need to wait. 142 + * No locking is needed because a controller cannot be resumed 143 + * while one of its companions is getting unbound. 144 + */ 145 + if (pdev->class == CL_EHCI) 146 + companion_common(pdev, hcd, WAIT_FOR_COMPANIONS); 147 + } 148 + 149 + #else /* !CONFIG_PM_SLEEP */ 150 + 151 + static inline void set_hs_companion(struct pci_dev *d, struct usb_hcd *h) {} 152 + static inline void clear_hs_companion(struct pci_dev *d, struct usb_hcd *h) {} 153 + static inline void wait_for_companions(struct pci_dev *d, struct usb_hcd *h) {} 154 + 155 + #endif /* !CONFIG_PM_SLEEP */ 41 156 42 157 /*-------------------------------------------------------------------------*/ 43 158 ··· 240 123 if (region == PCI_ROM_RESOURCE) { 241 124 dev_dbg(&dev->dev, "no i/o regions available\n"); 242 125 retval = -EBUSY; 243 - goto err1; 126 + goto err2; 244 127 } 245 128 } 246 129 ··· 249 132 retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); 250 133 if (retval != 0) 251 134 goto err4; 135 + set_hs_companion(dev, hcd); 252 136 return retval; 253 137 254 138 err4: ··· 260 142 } else 261 143 release_region(hcd->rsrc_start, hcd->rsrc_len); 262 144 err2: 145 + clear_hs_companion(dev, hcd); 263 146 usb_put_hcd(hcd); 264 147 err1: 265 148 pci_disable_device(dev); ··· 299 180 } else { 300 181 release_region(hcd->rsrc_start, hcd->rsrc_len); 301 182 } 183 + clear_hs_companion(dev, hcd); 302 184 usb_put_hcd(hcd); 303 185 pci_disable_device(dev); 304 186 } ··· 464 344 clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); 465 345 466 346 if (hcd->driver->pci_resume) { 347 + /* This call should be made only during system resume, 348 + * not during runtime resume. 349 + */ 350 + wait_for_companions(pci_dev, hcd); 351 + 467 352 retval = hcd->driver->pci_resume(hcd, hibernated); 468 353 if (retval) { 469 354 dev_err(dev, "PCI post-resume error %d!\n", retval);
+1
drivers/usb/core/hub.c
··· 1817 1817 /* Tell the world! */ 1818 1818 announce_device(udev); 1819 1819 1820 + device_enable_async_suspend(&udev->dev); 1820 1821 /* Register the device. The device driver is responsible 1821 1822 * for configuring the device and invoking the add-device 1822 1823 * notifier chain (used by usbfs and possibly others).
+1
drivers/usb/core/message.c
··· 1867 1867 "adding %s (config #%d, interface %d)\n", 1868 1868 dev_name(&intf->dev), configuration, 1869 1869 intf->cur_altsetting->desc.bInterfaceNumber); 1870 + device_enable_async_suspend(&intf->dev); 1870 1871 ret = device_add(&intf->dev); 1871 1872 if (ret != 0) { 1872 1873 dev_err(&dev->dev, "device_add(%s) --> %d\n",
+17
include/linux/device.h
··· 472 472 return dev->kobj.state_in_sysfs; 473 473 } 474 474 475 + static inline void device_enable_async_suspend(struct device *dev) 476 + { 477 + if (dev->power.status == DPM_ON) 478 + dev->power.async_suspend = true; 479 + } 480 + 481 + static inline void device_disable_async_suspend(struct device *dev) 482 + { 483 + if (dev->power.status == DPM_ON) 484 + dev->power.async_suspend = false; 485 + } 486 + 487 + static inline bool device_async_suspend_enabled(struct device *dev) 488 + { 489 + return !!dev->power.async_suspend; 490 + } 491 + 475 492 void driver_init(void); 476 493 477 494 /*
+6
include/linux/pm.h
··· 26 26 #include <linux/spinlock.h> 27 27 #include <linux/wait.h> 28 28 #include <linux/timer.h> 29 + #include <linux/completion.h> 29 30 30 31 /* 31 32 * Callbacks for platform drivers to implement. ··· 413 412 pm_message_t power_state; 414 413 unsigned int can_wakeup:1; 415 414 unsigned int should_wakeup:1; 415 + unsigned async_suspend:1; 416 416 enum dpm_state status; /* Owned by the PM core */ 417 417 #ifdef CONFIG_PM_SLEEP 418 418 struct list_head entry; 419 + struct completion completion; 419 420 #endif 420 421 #ifdef CONFIG_PM_RUNTIME 421 422 struct timer_list suspend_timer; ··· 433 430 unsigned int request_pending:1; 434 431 unsigned int deferred_resume:1; 435 432 unsigned int run_wake:1; 433 + unsigned int runtime_auto:1; 436 434 enum rpm_request request; 437 435 enum rpm_status runtime_status; 438 436 int runtime_error; ··· 512 508 __suspend_report_result(__func__, fn, ret); \ 513 509 } while (0) 514 510 511 + extern void device_pm_wait_for_dev(struct device *sub, struct device *dev); 515 512 #else /* !CONFIG_PM_SLEEP */ 516 513 517 514 #define device_pm_lock() do {} while (0) ··· 525 520 526 521 #define suspend_report_result(fn, ret) do {} while (0) 527 522 523 + static inline void device_pm_wait_for_dev(struct device *a, struct device *b) {} 528 524 #endif /* !CONFIG_PM_SLEEP */ 529 525 530 526 /* How to reorder dpm_list after device_move() */
+4
include/linux/pm_runtime.h
··· 28 28 extern int pm_runtime_barrier(struct device *dev); 29 29 extern void pm_runtime_enable(struct device *dev); 30 30 extern void __pm_runtime_disable(struct device *dev, bool check_resume); 31 + extern void pm_runtime_allow(struct device *dev); 32 + extern void pm_runtime_forbid(struct device *dev); 31 33 32 34 static inline bool pm_children_suspended(struct device *dev) 33 35 { ··· 80 78 static inline int pm_runtime_barrier(struct device *dev) { return 0; } 81 79 static inline void pm_runtime_enable(struct device *dev) {} 82 80 static inline void __pm_runtime_disable(struct device *dev, bool c) {} 81 + static inline void pm_runtime_allow(struct device *dev) {} 82 + static inline void pm_runtime_forbid(struct device *dev) {} 83 83 84 84 static inline bool pm_children_suspended(struct device *dev) { return false; } 85 85 static inline void pm_suspend_ignore_children(struct device *dev, bool en) {}
+7
include/linux/resume-trace.h
··· 6 6 7 7 extern int pm_trace_enabled; 8 8 9 + static inline int pm_trace_is_enabled(void) 10 + { 11 + return pm_trace_enabled; 12 + } 13 + 9 14 struct device; 10 15 extern void set_trace_device(struct device *); 11 16 extern void generate_resume_trace(const void *tracedata, unsigned int user); ··· 21 16 } while(0) 22 17 23 18 #else 19 + 20 + static inline int pm_trace_is_enabled(void) { return 0; } 24 21 25 22 #define TRACE_DEVICE(dev) do { } while (0) 26 23 #define TRACE_RESUME(dev) do { } while (0)
+1
include/linux/usb.h
··· 339 339 340 340 struct usb_devmap devmap; /* device address allocation map */ 341 341 struct usb_device *root_hub; /* Root hub */ 342 + struct usb_bus *hs_companion; /* Companion EHCI bus, if any */ 342 343 struct list_head bus_list; /* list of busses */ 343 344 344 345 int bandwidth_allocated; /* on this bus: how much of the time
+14
kernel/power/Kconfig
··· 27 27 code. This is helpful when debugging and reporting PM bugs, like 28 28 suspend support. 29 29 30 + config PM_ADVANCED_DEBUG 31 + bool "Extra PM attributes in sysfs for low-level debugging/testing" 32 + depends on PM_DEBUG 33 + default n 34 + ---help--- 35 + Add extra sysfs attributes allowing one to access some Power Management 36 + fields of device objects from user space. If you are not a kernel 37 + developer interested in debugging/testing Power Management, say "no". 38 + 30 39 config PM_VERBOSE 31 40 bool "Verbose Power Management debugging" 32 41 depends on PM_DEBUG ··· 93 84 bool 94 85 depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE 95 86 default y 87 + 88 + config PM_SLEEP_ADVANCED_DEBUG 89 + bool 90 + depends on PM_ADVANCED_DEBUG 91 + default n 96 92 97 93 config SUSPEND 98 94 bool "Suspend to RAM and standby"
+30 -1
kernel/power/main.c
··· 44 44 == NOTIFY_BAD) ? -EINVAL : 0; 45 45 } 46 46 47 + /* If set, devices may be suspended and resumed asynchronously. */ 48 + int pm_async_enabled = 1; 49 + 50 + static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr, 51 + char *buf) 52 + { 53 + return sprintf(buf, "%d\n", pm_async_enabled); 54 + } 55 + 56 + static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr, 57 + const char *buf, size_t n) 58 + { 59 + unsigned long val; 60 + 61 + if (strict_strtoul(buf, 10, &val)) 62 + return -EINVAL; 63 + 64 + if (val > 1) 65 + return -EINVAL; 66 + 67 + pm_async_enabled = val; 68 + return n; 69 + } 70 + 71 + power_attr(pm_async); 72 + 47 73 #ifdef CONFIG_PM_DEBUG 48 74 int pm_test_level = TEST_NONE; 49 75 ··· 234 208 #ifdef CONFIG_PM_TRACE 235 209 &pm_trace_attr.attr, 236 210 #endif 237 - #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PM_DEBUG) 211 + #ifdef CONFIG_PM_SLEEP 212 + &pm_async_attr.attr, 213 + #ifdef CONFIG_PM_DEBUG 238 214 &pm_test_attr.attr, 215 + #endif 239 216 #endif 240 217 NULL, 241 218 };
+2 -2
kernel/power/snapshot.c
··· 1181 1181 1182 1182 memory_bm_position_reset(&copy_bm); 1183 1183 1184 - while (to_free_normal > 0 && to_free_highmem > 0) { 1184 + while (to_free_normal > 0 || to_free_highmem > 0) { 1185 1185 unsigned long pfn = memory_bm_next_pfn(&copy_bm); 1186 1186 struct page *page = pfn_to_page(pfn); 1187 1187 ··· 1500 1500 { 1501 1501 unsigned int nr_pages, nr_highmem; 1502 1502 1503 - printk(KERN_INFO "PM: Creating hibernation image: \n"); 1503 + printk(KERN_INFO "PM: Creating hibernation image:\n"); 1504 1504 1505 1505 drain_local_pages(NULL); 1506 1506 nr_pages = count_data_pages();
-4
kernel/power/swap.c
··· 657 657 struct swsusp_info *header; 658 658 659 659 *flags_p = swsusp_header->flags; 660 - if (IS_ERR(resume_bdev)) { 661 - pr_debug("PM: Image device not initialised\n"); 662 - return PTR_ERR(resume_bdev); 663 - } 664 660 665 661 memset(&snapshot, 0, sizeof(struct snapshot_handle)); 666 662 error = snapshot_write_next(&snapshot, PAGE_SIZE);
-58
kernel/power/swsusp.c
··· 1 - /* 2 - * linux/kernel/power/swsusp.c 3 - * 4 - * This file provides code to write suspend image to swap and read it back. 5 - * 6 - * Copyright (C) 1998-2001 Gabor Kuti <seasons@fornax.hu> 7 - * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@suse.cz> 8 - * 9 - * This file is released under the GPLv2. 10 - * 11 - * I'd like to thank the following people for their work: 12 - * 13 - * Pavel Machek <pavel@ucw.cz>: 14 - * Modifications, defectiveness pointing, being with me at the very beginning, 15 - * suspend to swap space, stop all tasks. Port to 2.4.18-ac and 2.5.17. 16 - * 17 - * Steve Doddi <dirk@loth.demon.co.uk>: 18 - * Support the possibility of hardware state restoring. 19 - * 20 - * Raph <grey.havens@earthling.net>: 21 - * Support for preserving states of network devices and virtual console 22 - * (including X and svgatextmode) 23 - * 24 - * Kurt Garloff <garloff@suse.de>: 25 - * Straightened the critical function in order to prevent compilers from 26 - * playing tricks with local variables. 27 - * 28 - * Andreas Mohr <a.mohr@mailto.de> 29 - * 30 - * Alex Badea <vampire@go.ro>: 31 - * Fixed runaway init 32 - * 33 - * Rafael J. Wysocki <rjw@sisk.pl> 34 - * Reworked the freeing of memory and the handling of swap 35 - * 36 - * More state savers are welcome. Especially for the scsi layer... 37 - * 38 - * For TODOs,FIXMEs also look in Documentation/power/swsusp.txt 39 - */ 40 - 41 - #include <linux/mm.h> 42 - #include <linux/suspend.h> 43 - #include <linux/spinlock.h> 44 - #include <linux/kernel.h> 45 - #include <linux/major.h> 46 - #include <linux/swap.h> 47 - #include <linux/pm.h> 48 - #include <linux/swapops.h> 49 - #include <linux/bootmem.h> 50 - #include <linux/syscalls.h> 51 - #include <linux/highmem.h> 52 - #include <linux/time.h> 53 - #include <linux/rbtree.h> 54 - #include <linux/io.h> 55 - 56 - #include "power.h" 57 - 58 - int in_suspend __nosavedata = 0;
+19 -4
kernel/power/user.c
··· 195 195 return res; 196 196 } 197 197 198 + static void snapshot_deprecated_ioctl(unsigned int cmd) 199 + { 200 + if (printk_ratelimit()) 201 + printk(KERN_NOTICE "%pf: ioctl '%.8x' is deprecated and will " 202 + "be removed soon, update your suspend-to-disk " 203 + "utilities\n", 204 + __builtin_return_address(0), cmd); 205 + } 206 + 198 207 static long snapshot_ioctl(struct file *filp, unsigned int cmd, 199 208 unsigned long arg) 200 209 { ··· 255 246 data->frozen = 0; 256 247 break; 257 248 258 - case SNAPSHOT_CREATE_IMAGE: 259 249 case SNAPSHOT_ATOMIC_SNAPSHOT: 250 + snapshot_deprecated_ioctl(cmd); 251 + case SNAPSHOT_CREATE_IMAGE: 260 252 if (data->mode != O_RDONLY || !data->frozen || data->ready) { 261 253 error = -EPERM; 262 254 break; ··· 285 275 data->ready = 0; 286 276 break; 287 277 288 - case SNAPSHOT_PREF_IMAGE_SIZE: 289 278 case SNAPSHOT_SET_IMAGE_SIZE: 279 + snapshot_deprecated_ioctl(cmd); 280 + case SNAPSHOT_PREF_IMAGE_SIZE: 290 281 image_size = arg; 291 282 break; 292 283 ··· 301 290 error = put_user(size, (loff_t __user *)arg); 302 291 break; 303 292 304 - case SNAPSHOT_AVAIL_SWAP_SIZE: 305 293 case SNAPSHOT_AVAIL_SWAP: 294 + snapshot_deprecated_ioctl(cmd); 295 + case SNAPSHOT_AVAIL_SWAP_SIZE: 306 296 size = count_swap_pages(data->swap, 1); 307 297 size <<= PAGE_SHIFT; 308 298 error = put_user(size, (loff_t __user *)arg); 309 299 break; 310 300 311 - case SNAPSHOT_ALLOC_SWAP_PAGE: 312 301 case SNAPSHOT_GET_SWAP_PAGE: 302 + snapshot_deprecated_ioctl(cmd); 303 + case SNAPSHOT_ALLOC_SWAP_PAGE: 313 304 if (data->swap < 0 || data->swap >= MAX_SWAPFILES) { 314 305 error = -ENODEV; 315 306 break; ··· 334 321 break; 335 322 336 323 case SNAPSHOT_SET_SWAP_FILE: /* This ioctl is deprecated */ 324 + snapshot_deprecated_ioctl(cmd); 337 325 if (!swsusp_swap_in_use()) { 338 326 /* 339 327 * User space encodes device types as two-byte values, ··· 376 362 break; 377 363 378 364 case SNAPSHOT_PMOPS: /* This ioctl is deprecated */ 365 + snapshot_deprecated_ioctl(cmd); 379 366 error = -EINVAL; 380 367 381 368 switch (arg) {