Merge branches 'pm-sleep' and 'pm-domains'

* pm-sleep:
PM / watchdog: iTCO: stop watchdog during system suspend
PM / sleep: add pm-trace support for suspending phase
PM / sleep: add configurable delay for pm_test

* pm-domains:
PM / domains: avoid potential oops in pm_genpd_remove_device()
PM / domains: factor out code to get the generic PM domain from a struct device
PM / domains: quieten down generic pm domains
PM / Domains: Sync runtime PM status with genpd after probe
driver core / PM: Add PM domain callbacks for device setup/cleanup
MAINTAINERS: add entry for Generic PM domains (genpd)

+189 -46
+7
Documentation/kernel-parameters.txt
··· 3462 3462 improve throughput, but will also increase the 3463 3463 amount of memory reserved for use by the client. 3464 3464 3465 + suspend.pm_test_delay= 3466 + [SUSPEND] 3467 + Sets the number of seconds to remain in a suspend test 3468 + mode before resuming the system (see 3469 + /sys/power/pm_test). Only available when CONFIG_PM_DEBUG 3470 + is set. Default value is 5. 3471 + 3465 3472 swapaccount=[0|1] 3466 3473 [KNL] Enable accounting of swap in memory resource 3467 3474 controller if no parameter or 1 is given or disable
+6 -4
Documentation/power/basic-pm-debugging.txt
··· 75 75 # echo platform > /sys/power/disk 76 76 # echo disk > /sys/power/state 77 77 78 - Then, the kernel will try to freeze processes, suspend devices, wait 5 seconds, 79 - resume devices and thaw processes. If "platform" is written to 78 + Then, the kernel will try to freeze processes, suspend devices, wait a few 79 + seconds (5 by default, but configurable by the suspend.pm_test_delay module 80 + parameter), resume devices and thaw processes. If "platform" is written to 80 81 /sys/power/pm_test , then after suspending devices the kernel will additionally 81 82 invoke the global control methods (eg. ACPI global control methods) used to 82 - prepare the platform firmware for hibernation. Next, it will wait 5 seconds and 83 - invoke the platform (eg. ACPI) global methods used to cancel hibernation etc. 83 + prepare the platform firmware for hibernation. Next, it will wait a 84 + configurable number of seconds and invoke the platform (eg. ACPI) global 85 + methods used to cancel hibernation etc. 84 86 85 87 Writing "none" to /sys/power/pm_test causes the kernel to switch to the normal 86 88 hibernation/suspend operations. Also, when open for reading, /sys/power/pm_test
+9
MAINTAINERS
··· 4312 4312 F: drivers/phy/ 4313 4313 F: include/linux/phy/ 4314 4314 4315 + GENERIC PM DOMAINS 4316 + M: "Rafael J. Wysocki" <rjw@rjwysocki.net> 4317 + M: Kevin Hilman <khilman@kernel.org> 4318 + M: Ulf Hansson <ulf.hansson@linaro.org> 4319 + L: linux-pm@vger.kernel.org 4320 + S: Supported 4321 + F: drivers/base/power/domain*.c 4322 + F: include/linux/pm_domain.h 4323 + 4315 4324 GENERIC UIO DRIVER FOR PCI DEVICES 4316 4325 M: "Michael S. Tsirkin" <mst@redhat.com> 4317 4326 L: kvm@vger.kernel.org
+6 -4
arch/x86/include/asm/resume-trace.h arch/x86/include/asm/pm-trace.h
··· 1 - #ifndef _ASM_X86_RESUME_TRACE_H 2 - #define _ASM_X86_RESUME_TRACE_H 1 + #ifndef _ASM_X86_PM_TRACE_H 2 + #define _ASM_X86_PM_TRACE_H 3 3 4 4 #include <asm/asm.h> 5 5 ··· 14 14 ".previous" \ 15 15 :"=r" (tracedata) \ 16 16 : "i" (__LINE__), "i" (__FILE__)); \ 17 - generate_resume_trace(tracedata, user); \ 17 + generate_pm_trace(tracedata, user); \ 18 18 } \ 19 19 } while (0) 20 20 21 - #endif /* _ASM_X86_RESUME_TRACE_H */ 21 + #define TRACE_SUSPEND(user) TRACE_RESUME(user) 22 + 23 + #endif /* _ASM_X86_PM_TRACE_H */
+14
drivers/base/dd.c
··· 298 298 goto probe_failed; 299 299 } 300 300 301 + if (dev->pm_domain && dev->pm_domain->activate) { 302 + ret = dev->pm_domain->activate(dev); 303 + if (ret) 304 + goto probe_failed; 305 + } 306 + 301 307 if (dev->bus->probe) { 302 308 ret = dev->bus->probe(dev); 303 309 if (ret) ··· 313 307 if (ret) 314 308 goto probe_failed; 315 309 } 310 + 311 + if (dev->pm_domain && dev->pm_domain->sync) 312 + dev->pm_domain->sync(dev); 316 313 317 314 driver_bound(dev); 318 315 ret = 1; ··· 328 319 driver_sysfs_remove(dev); 329 320 dev->driver = NULL; 330 321 dev_set_drvdata(dev, NULL); 322 + if (dev->pm_domain && dev->pm_domain->dismiss) 323 + dev->pm_domain->dismiss(dev); 331 324 332 325 if (ret == -EPROBE_DEFER) { 333 326 /* Driver requested deferred probing */ ··· 536 525 devres_release_all(dev); 537 526 dev->driver = NULL; 538 527 dev_set_drvdata(dev, NULL); 528 + if (dev->pm_domain && dev->pm_domain->dismiss) 529 + dev->pm_domain->dismiss(dev); 530 + 539 531 klist_remove(&dev->p->knode_driver); 540 532 if (dev->bus) 541 533 blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+49 -21
drivers/base/power/domain.c
··· 68 68 return genpd; 69 69 } 70 70 71 - struct generic_pm_domain *dev_to_genpd(struct device *dev) 71 + /* 72 + * Get the generic PM domain for a particular struct device. 73 + * This validates the struct device pointer, the PM domain pointer, 74 + * and checks that the PM domain pointer is a real generic PM domain. 75 + * Any failure results in NULL being returned. 76 + */ 77 + struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev) 78 + { 79 + struct generic_pm_domain *genpd = NULL, *gpd; 80 + 81 + if (IS_ERR_OR_NULL(dev) || IS_ERR_OR_NULL(dev->pm_domain)) 82 + return NULL; 83 + 84 + mutex_lock(&gpd_list_lock); 85 + list_for_each_entry(gpd, &gpd_list, gpd_list_node) { 86 + if (&gpd->domain == dev->pm_domain) { 87 + genpd = gpd; 88 + break; 89 + } 90 + } 91 + mutex_unlock(&gpd_list_lock); 92 + 93 + return genpd; 94 + } 95 + 96 + /* 97 + * This should only be used where we are certain that the pm_domain 98 + * attached to the device is a genpd domain. 99 + */ 100 + static struct generic_pm_domain *dev_to_genpd(struct device *dev) 72 101 { 73 102 if (IS_ERR_OR_NULL(dev->pm_domain)) 74 103 return ERR_PTR(-EINVAL); ··· 202 173 genpd->power_on_latency_ns = elapsed_ns; 203 174 genpd->max_off_time_changed = true; 204 175 genpd_recalc_cpu_exit_latency(genpd); 205 - pr_warn("%s: Power-%s latency exceeded, new value %lld ns\n", 206 - genpd->name, "on", elapsed_ns); 176 + pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", 177 + genpd->name, "on", elapsed_ns); 207 178 208 179 return ret; 209 180 } ··· 228 199 229 200 genpd->power_off_latency_ns = elapsed_ns; 230 201 genpd->max_off_time_changed = true; 231 - pr_warn("%s: Power-%s latency exceeded, new value %lld ns\n", 232 - genpd->name, "off", elapsed_ns); 202 + pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", 203 + genpd->name, "off", elapsed_ns); 233 204 234 205 return ret; 235 206 } ··· 1542 1513 1543 1514 dev_dbg(dev, "%s()\n", __func__); 1544 1515 1545 - if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev) 1546 - || IS_ERR_OR_NULL(dev->pm_domain) 1547 - || pd_to_genpd(dev->pm_domain) != genpd) 1516 + if (!genpd || genpd != pm_genpd_lookup_dev(dev)) 1548 1517 return -EINVAL; 1549 1518 1550 1519 /* The above validation also means we have existing domain_data. */ ··· 2120 2093 */ 2121 2094 static void genpd_dev_pm_detach(struct device *dev, bool power_off) 2122 2095 { 2123 - struct generic_pm_domain *pd = NULL, *gpd; 2096 + struct generic_pm_domain *pd; 2124 2097 int ret = 0; 2125 2098 2126 - if (!dev->pm_domain) 2127 - return; 2128 - 2129 - mutex_lock(&gpd_list_lock); 2130 - list_for_each_entry(gpd, &gpd_list, gpd_list_node) { 2131 - if (&gpd->domain == dev->pm_domain) { 2132 - pd = gpd; 2133 - break; 2134 - } 2135 - } 2136 - mutex_unlock(&gpd_list_lock); 2137 - 2099 + pd = pm_genpd_lookup_dev(dev); 2138 2100 if (!pd) 2139 2101 return; 2140 2102 ··· 2143 2127 } 2144 2128 2145 2129 /* Check if PM domain can be powered off after removing this device. */ 2130 + genpd_queue_power_off_work(pd); 2131 + } 2132 + 2133 + static void genpd_dev_pm_sync(struct device *dev) 2134 + { 2135 + struct generic_pm_domain *pd; 2136 + 2137 + pd = dev_to_genpd(dev); 2138 + if (IS_ERR(pd)) 2139 + return; 2140 + 2146 2141 genpd_queue_power_off_work(pd); 2147 2142 } 2148 2143 ··· 2223 2196 } 2224 2197 2225 2198 dev->pm_domain->detach = genpd_dev_pm_detach; 2199 + dev->pm_domain->sync = genpd_dev_pm_sync; 2226 2200 pm_genpd_poweron(pd); 2227 2201 2228 2202 return 0;
+16 -4
drivers/base/power/main.c
··· 23 23 #include <linux/mutex.h> 24 24 #include <linux/pm.h> 25 25 #include <linux/pm_runtime.h> 26 - #include <linux/resume-trace.h> 26 + #include <linux/pm-trace.h> 27 27 #include <linux/interrupt.h> 28 28 #include <linux/sched.h> 29 29 #include <linux/async.h> ··· 1017 1017 char *info = NULL; 1018 1018 int error = 0; 1019 1019 1020 + TRACE_DEVICE(dev); 1021 + TRACE_SUSPEND(0); 1022 + 1020 1023 if (async_error) 1021 1024 goto Complete; 1022 1025 ··· 1060 1057 1061 1058 Complete: 1062 1059 complete_all(&dev->power.completion); 1060 + TRACE_SUSPEND(error); 1063 1061 return error; 1064 1062 } 1065 1063 ··· 1082 1078 { 1083 1079 reinit_completion(&dev->power.completion); 1084 1080 1085 - if (pm_async_enabled && dev->power.async_suspend) { 1081 + if (is_async(dev)) { 1086 1082 get_device(dev); 1087 1083 async_schedule(async_suspend_noirq, dev); 1088 1084 return 0; ··· 1161 1157 char *info = NULL; 1162 1158 int error = 0; 1163 1159 1160 + TRACE_DEVICE(dev); 1161 + TRACE_SUSPEND(0); 1162 + 1164 1163 __pm_runtime_disable(dev, false); 1165 1164 1166 1165 if (async_error) ··· 1205 1198 async_error = error; 1206 1199 1207 1200 Complete: 1201 + TRACE_SUSPEND(error); 1208 1202 complete_all(&dev->power.completion); 1209 1203 return error; 1210 1204 } ··· 1227 1219 { 1228 1220 reinit_completion(&dev->power.completion); 1229 1221 1230 - if (pm_async_enabled && dev->power.async_suspend) { 1222 + if (is_async(dev)) { 1231 1223 get_device(dev); 1232 1224 async_schedule(async_suspend_late, dev); 1233 1225 return 0; ··· 1346 1338 int error = 0; 1347 1339 DECLARE_DPM_WATCHDOG_ON_STACK(wd); 1348 1340 1341 + TRACE_DEVICE(dev); 1342 + TRACE_SUSPEND(0); 1343 + 1349 1344 dpm_wait_for_children(dev, async); 1350 1345 1351 1346 if (async_error) ··· 1455 1444 if (error) 1456 1445 async_error = error; 1457 1446 1447 + TRACE_SUSPEND(error); 1458 1448 return error; 1459 1449 } 1460 1450 ··· 1477 1465 { 1478 1466 reinit_completion(&dev->power.completion); 1479 1467 1480 - if (pm_async_enabled && dev->power.async_suspend) { 1468 + if (is_async(dev)) { 1481 1469 get_device(dev); 1482 1470 async_schedule(async_suspend, dev); 1483 1471 return 0;
+3 -3
drivers/base/power/trace.c
··· 7 7 * devices may be working. 8 8 */ 9 9 10 - #include <linux/resume-trace.h> 10 + #include <linux/pm-trace.h> 11 11 #include <linux/export.h> 12 12 #include <linux/rtc.h> 13 13 ··· 154 154 * it's not any guarantee, but it's a high _likelihood_ that 155 155 * the match is valid). 156 156 */ 157 - void generate_resume_trace(const void *tracedata, unsigned int user) 157 + void generate_pm_trace(const void *tracedata, unsigned int user) 158 158 { 159 159 unsigned short lineno = *(unsigned short *)tracedata; 160 160 const char *file = *(const char **)(tracedata + 2); ··· 164 164 file_hash_value = hash_string(lineno, file, FILEHASH); 165 165 set_magic_time(user_hash_value, file_hash_value, dev_hash_value); 166 166 } 167 - EXPORT_SYMBOL(generate_resume_trace); 167 + EXPORT_SYMBOL(generate_pm_trace); 168 168 169 169 extern char __tracedata_start, __tracedata_end; 170 170 static int show_file_hash(unsigned int value)
+51
drivers/watchdog/iTCO_wdt.c
··· 51 51 #define DRV_VERSION "1.11" 52 52 53 53 /* Includes */ 54 + #include <linux/acpi.h> /* For ACPI support */ 54 55 #include <linux/module.h> /* For module specific items */ 55 56 #include <linux/moduleparam.h> /* For new moduleparam's */ 56 57 #include <linux/types.h> /* For standard types (like size_t) */ ··· 104 103 struct platform_device *dev; 105 104 /* the PCI-device */ 106 105 struct pci_dev *pdev; 106 + /* whether or not the watchdog has been suspended */ 107 + bool suspended; 107 108 } iTCO_wdt_private; 108 109 109 110 /* module parameters */ ··· 574 571 iTCO_wdt_stop(NULL); 575 572 } 576 573 574 + #ifdef CONFIG_PM_SLEEP 575 + /* 576 + * Suspend-to-idle requires this, because it stops the ticks and timekeeping, so 577 + * the watchdog cannot be pinged while in that state. In ACPI sleep states the 578 + * watchdog is stopped by the platform firmware. 579 + */ 580 + 581 + #ifdef CONFIG_ACPI 582 + static inline bool need_suspend(void) 583 + { 584 + return acpi_target_system_state() == ACPI_STATE_S0; 585 + } 586 + #else 587 + static inline bool need_suspend(void) { return true; } 588 + #endif 589 + 590 + static int iTCO_wdt_suspend_noirq(struct device *dev) 591 + { 592 + int ret = 0; 593 + 594 + iTCO_wdt_private.suspended = false; 595 + if (watchdog_active(&iTCO_wdt_watchdog_dev) && need_suspend()) { 596 + ret = iTCO_wdt_stop(&iTCO_wdt_watchdog_dev); 597 + if (!ret) 598 + iTCO_wdt_private.suspended = true; 599 + } 600 + return ret; 601 + } 602 + 603 + static int iTCO_wdt_resume_noirq(struct device *dev) 604 + { 605 + if (iTCO_wdt_private.suspended) 606 + iTCO_wdt_start(&iTCO_wdt_watchdog_dev); 607 + 608 + return 0; 609 + } 610 + 611 + static struct dev_pm_ops iTCO_wdt_pm = { 612 + .suspend_noirq = iTCO_wdt_suspend_noirq, 613 + .resume_noirq = iTCO_wdt_resume_noirq, 614 + }; 615 + 616 + #define ITCO_WDT_PM_OPS (&iTCO_wdt_pm) 617 + #else 618 + #define ITCO_WDT_PM_OPS NULL 619 + #endif /* CONFIG_PM_SLEEP */ 620 + 577 621 static struct platform_driver iTCO_wdt_driver = { 578 622 .probe = iTCO_wdt_probe, 579 623 .remove = iTCO_wdt_remove, 580 624 .shutdown = iTCO_wdt_shutdown, 581 625 .driver = { 582 626 .name = DRV_NAME, 627 + .pm = ITCO_WDT_PM_OPS, 583 628 }, 584 629 }; 585 630
+8
include/linux/pm.h
··· 603 603 * Power domains provide callbacks that are executed during system suspend, 604 604 * hibernation, system resume and during runtime PM transitions along with 605 605 * subsystem-level and driver-level callbacks. 606 + * 607 + * @detach: Called when removing a device from the domain. 608 + * @activate: Called before executing probe routines for bus types and drivers. 609 + * @sync: Called after successful driver probe. 610 + * @dismiss: Called after unsuccessful driver probe and after driver removal. 606 611 */ 607 612 struct dev_pm_domain { 608 613 struct dev_pm_ops ops; 609 614 void (*detach)(struct device *dev, bool power_off); 615 + int (*activate)(struct device *dev); 616 + void (*sync)(struct device *dev); 617 + void (*dismiss)(struct device *dev); 610 618 }; 611 619 612 620 /*
+3 -3
include/linux/pm_domain.h
··· 127 127 return to_gpd_data(dev->power.subsys_data->domain_data); 128 128 } 129 129 130 - extern struct generic_pm_domain *dev_to_genpd(struct device *dev); 130 + extern struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev); 131 131 extern int __pm_genpd_add_device(struct generic_pm_domain *genpd, 132 132 struct device *dev, 133 133 struct gpd_timing_data *td); ··· 163 163 { 164 164 return ERR_PTR(-ENOSYS); 165 165 } 166 - static inline struct generic_pm_domain *dev_to_genpd(struct device *dev) 166 + static inline struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev) 167 167 { 168 - return ERR_PTR(-ENOSYS); 168 + return NULL; 169 169 } 170 170 static inline int __pm_genpd_add_device(struct generic_pm_domain *genpd, 171 171 struct device *dev,
+5 -4
include/linux/resume-trace.h include/linux/pm-trace.h
··· 1 - #ifndef RESUME_TRACE_H 2 - #define RESUME_TRACE_H 1 + #ifndef PM_TRACE_H 2 + #define PM_TRACE_H 3 3 4 4 #ifdef CONFIG_PM_TRACE 5 - #include <asm/resume-trace.h> 5 + #include <asm/pm-trace.h> 6 6 #include <linux/types.h> 7 7 8 8 extern int pm_trace_enabled; ··· 14 14 15 15 struct device; 16 16 extern void set_trace_device(struct device *); 17 - extern void generate_resume_trace(const void *tracedata, unsigned int user); 17 + extern void generate_pm_trace(const void *tracedata, unsigned int user); 18 18 extern int show_trace_dev_match(char *buf, size_t size); 19 19 20 20 #define TRACE_DEVICE(dev) do { \ ··· 28 28 29 29 #define TRACE_DEVICE(dev) do { } while (0) 30 30 #define TRACE_RESUME(dev) do { } while (0) 31 + #define TRACE_SUSPEND(dev) do { } while (0) 31 32 32 33 #endif 33 34
+1 -1
kernel/power/main.c
··· 11 11 #include <linux/export.h> 12 12 #include <linux/kobject.h> 13 13 #include <linux/string.h> 14 - #include <linux/resume-trace.h> 14 + #include <linux/pm-trace.h> 15 15 #include <linux/workqueue.h> 16 16 #include <linux/debugfs.h> 17 17 #include <linux/seq_file.h>
+11 -2
kernel/power/suspend.c
··· 28 28 #include <linux/ftrace.h> 29 29 #include <trace/events/power.h> 30 30 #include <linux/compiler.h> 31 + #include <linux/moduleparam.h> 31 32 32 33 #include "power.h" 33 34 ··· 234 233 suspend_ops->suspend_again() : false; 235 234 } 236 235 236 + #ifdef CONFIG_PM_DEBUG 237 + static unsigned int pm_test_delay = 5; 238 + module_param(pm_test_delay, uint, 0644); 239 + MODULE_PARM_DESC(pm_test_delay, 240 + "Number of seconds to wait before resuming from suspend test"); 241 + #endif 242 + 237 243 static int suspend_test(int level) 238 244 { 239 245 #ifdef CONFIG_PM_DEBUG 240 246 if (pm_test_level == level) { 241 - printk(KERN_INFO "suspend debug: Waiting for 5 seconds.\n"); 242 - mdelay(5000); 247 + printk(KERN_INFO "suspend debug: Waiting for %d second(s).\n", 248 + pm_test_delay); 249 + mdelay(pm_test_delay * 1000); 243 250 return 1; 244 251 } 245 252 #endif /* !CONFIG_PM_DEBUG */