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