diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-06-28 07:01:40 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-06-28 07:01:40 -0400 |
commit | e52cff8bdd4a30c40a7f65c7ea8f1f425f8a15eb (patch) | |
tree | 1729332ebab51bb560ca64effe46cdab38ab537f | |
parent | 405a1086bdd091d2d55db0ac905cd6332b35cec1 (diff) | |
parent | f5ce1572109049b90484e2bb44927cb6034c5eb1 (diff) |
Merge branch 'pm-assorted'
* pm-assorted:
PM / QoS: Add pm_qos and dev_pm_qos to events-power.txt
PM / QoS: Add dev_pm_qos_request tracepoints
PM / QoS: Add pm_qos_request tracepoints
PM / QoS: Add pm_qos_update_target/flags tracepoints
PM / QoS: Update Documentation/power/pm_qos_interface.txt
PM / Sleep: Print last wakeup source on failed wakeup_count write
PM / QoS: correct the valid range of pm_qos_class
PM / wakeup: Adjust messaging for wake events during suspend
PM / Runtime: Update .runtime_idle() callback documentation
PM / Runtime: Rework the "runtime idle" helper routine
PM / Hibernate: print physical addresses consistently with other parts of kernel
33 files changed, 315 insertions, 113 deletions
diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt index 79a2a58425ee..483632087788 100644 --- a/Documentation/power/pm_qos_interface.txt +++ b/Documentation/power/pm_qos_interface.txt | |||
@@ -7,7 +7,7 @@ one of the parameters. | |||
7 | Two different PM QoS frameworks are available: | 7 | Two different PM QoS frameworks are available: |
8 | 1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput. | 8 | 1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput. |
9 | 2. the per-device PM QoS framework provides the API to manage the per-device latency | 9 | 2. the per-device PM QoS framework provides the API to manage the per-device latency |
10 | constraints. | 10 | constraints and PM QoS flags. |
11 | 11 | ||
12 | Each parameters have defined units: | 12 | Each parameters have defined units: |
13 | * latency: usec | 13 | * latency: usec |
@@ -86,13 +86,17 @@ To remove the user mode request for a target value simply close the device | |||
86 | node. | 86 | node. |
87 | 87 | ||
88 | 88 | ||
89 | 2. PM QoS per-device latency framework | 89 | 2. PM QoS per-device latency and flags framework |
90 | |||
91 | For each device, there are two lists of PM QoS requests. One is maintained | ||
92 | along with the aggregated target of latency value and the other is for PM QoS | ||
93 | flags. Values are updated in response to changes of the request list. | ||
94 | |||
95 | Target latency value is simply the minimum of the request values held in the | ||
96 | parameter list elements. The PM QoS flags aggregate value is a gather (bitwise | ||
97 | OR) of all list elements' values. Two device PM QoS flags are defined currently: | ||
98 | PM_QOS_FLAG_NO_POWER_OFF and PM_QOS_FLAG_REMOTE_WAKEUP. | ||
90 | 99 | ||
91 | For each device a list of performance requests is maintained along with | ||
92 | an aggregated target value. The aggregated target value is updated with | ||
93 | changes to the request list or elements of the list. Typically the | ||
94 | aggregated target value is simply the max or min of the request values held | ||
95 | in the parameter list elements. | ||
96 | Note: the aggregated target value is implemented as an atomic variable so that | 100 | Note: the aggregated target value is implemented as an atomic variable so that |
97 | reading the aggregated value does not require any locking mechanism. | 101 | reading the aggregated value does not require any locking mechanism. |
98 | 102 | ||
@@ -119,6 +123,38 @@ the request. | |||
119 | s32 dev_pm_qos_read_value(device): | 123 | s32 dev_pm_qos_read_value(device): |
120 | Returns the aggregated value for a given device's constraints list. | 124 | Returns the aggregated value for a given device's constraints list. |
121 | 125 | ||
126 | enum pm_qos_flags_status dev_pm_qos_flags(device, mask) | ||
127 | Check PM QoS flags of the given device against the given mask of flags. | ||
128 | The meaning of the return values is as follows: | ||
129 | PM_QOS_FLAGS_ALL: All flags from the mask are set | ||
130 | PM_QOS_FLAGS_SOME: Some flags from the mask are set | ||
131 | PM_QOS_FLAGS_NONE: No flags from the mask are set | ||
132 | PM_QOS_FLAGS_UNDEFINED: The device's PM QoS structure has not been | ||
133 | initialized or the list of requests is empty. | ||
134 | |||
135 | int dev_pm_qos_add_ancestor_request(dev, handle, value) | ||
136 | Add a PM QoS request for the first direct ancestor of the given device whose | ||
137 | power.ignore_children flag is unset. | ||
138 | |||
139 | int dev_pm_qos_expose_latency_limit(device, value) | ||
140 | Add a request to the device's PM QoS list of latency constraints and create | ||
141 | a sysfs attribute pm_qos_resume_latency_us under the device's power directory | ||
142 | allowing user space to manipulate that request. | ||
143 | |||
144 | void dev_pm_qos_hide_latency_limit(device) | ||
145 | Drop the request added by dev_pm_qos_expose_latency_limit() from the device's | ||
146 | PM QoS list of latency constraints and remove sysfs attribute pm_qos_resume_latency_us | ||
147 | from the device's power directory. | ||
148 | |||
149 | int dev_pm_qos_expose_flags(device, value) | ||
150 | Add a request to the device's PM QoS list of flags and create sysfs attributes | ||
151 | pm_qos_no_power_off and pm_qos_remote_wakeup under the device's power directory | ||
152 | allowing user space to change these flags' value. | ||
153 | |||
154 | void dev_pm_qos_hide_flags(device) | ||
155 | Drop the request added by dev_pm_qos_expose_flags() from the device's PM QoS list | ||
156 | of flags and remove sysfs attributes pm_qos_no_power_off and pm_qos_remote_wakeup | ||
157 | under the device's power directory. | ||
122 | 158 | ||
123 | Notification mechanisms: | 159 | Notification mechanisms: |
124 | The per-device PM QoS framework has 2 different and distinct notification trees: | 160 | The per-device PM QoS framework has 2 different and distinct notification trees: |
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 6c9f5d9aa115..71d8fe4e75d3 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt | |||
@@ -144,8 +144,12 @@ The action performed by the idle callback is totally dependent on the subsystem | |||
144 | (or driver) in question, but the expected and recommended action is to check | 144 | (or driver) in question, but the expected and recommended action is to check |
145 | if the device can be suspended (i.e. if all of the conditions necessary for | 145 | if the device can be suspended (i.e. if all of the conditions necessary for |
146 | suspending the device are satisfied) and to queue up a suspend request for the | 146 | suspending the device are satisfied) and to queue up a suspend request for the |
147 | device in that case. The value returned by this callback is ignored by the PM | 147 | device in that case. If there is no idle callback, or if the callback returns |
148 | core. | 148 | 0, then the PM core will attempt to carry out a runtime suspend of the device; |
149 | in essence, it will call pm_runtime_suspend() directly. To prevent this (for | ||
150 | example, if the callback routine has started a delayed suspend), the routine | ||
151 | should return a non-zero value. Negative error return codes are ignored by the | ||
152 | PM core. | ||
149 | 153 | ||
150 | The helper functions provided by the PM core, described in Section 4, guarantee | 154 | The helper functions provided by the PM core, described in Section 4, guarantee |
151 | that the following constraints are met with respect to runtime PM callbacks for | 155 | that the following constraints are met with respect to runtime PM callbacks for |
@@ -301,9 +305,10 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: | |||
301 | removing the device from device hierarchy | 305 | removing the device from device hierarchy |
302 | 306 | ||
303 | int pm_runtime_idle(struct device *dev); | 307 | int pm_runtime_idle(struct device *dev); |
304 | - execute the subsystem-level idle callback for the device; returns 0 on | 308 | - execute the subsystem-level idle callback for the device; returns an |
305 | success or error code on failure, where -EINPROGRESS means that | 309 | error code on failure, where -EINPROGRESS means that ->runtime_idle() is |
306 | ->runtime_idle() is already being executed | 310 | already being executed; if there is no callback or the callback returns 0 |
311 | then run pm_runtime_suspend(dev) and return its result | ||
307 | 312 | ||
308 | int pm_runtime_suspend(struct device *dev); | 313 | int pm_runtime_suspend(struct device *dev); |
309 | - execute the subsystem-level suspend callback for the device; returns 0 on | 314 | - execute the subsystem-level suspend callback for the device; returns 0 on |
@@ -660,11 +665,6 @@ Subsystems may wish to conserve code space by using the set of generic power | |||
660 | management callbacks provided by the PM core, defined in | 665 | management callbacks provided by the PM core, defined in |
661 | driver/base/power/generic_ops.c: | 666 | driver/base/power/generic_ops.c: |
662 | 667 | ||
663 | int pm_generic_runtime_idle(struct device *dev); | ||
664 | - invoke the ->runtime_idle() callback provided by the driver of this | ||
665 | device, if defined, and call pm_runtime_suspend() for this device if the | ||
666 | return value is 0 or the callback is not defined | ||
667 | |||
668 | int pm_generic_runtime_suspend(struct device *dev); | 668 | int pm_generic_runtime_suspend(struct device *dev); |
669 | - invoke the ->runtime_suspend() callback provided by the driver of this | 669 | - invoke the ->runtime_suspend() callback provided by the driver of this |
670 | device and return its result, or return -EINVAL if not defined | 670 | device and return its result, or return -EINVAL if not defined |
diff --git a/Documentation/trace/events-power.txt b/Documentation/trace/events-power.txt index e1498ff8cf94..3bd33b8dc7c4 100644 --- a/Documentation/trace/events-power.txt +++ b/Documentation/trace/events-power.txt | |||
@@ -63,3 +63,34 @@ power_domain_target "%s state=%lu cpu_id=%lu" | |||
63 | The first parameter gives the power domain name (e.g. "mpu_pwrdm"). | 63 | The first parameter gives the power domain name (e.g. "mpu_pwrdm"). |
64 | The second parameter is the power domain target state. | 64 | The second parameter is the power domain target state. |
65 | 65 | ||
66 | 4. PM QoS events | ||
67 | ================ | ||
68 | The PM QoS events are used for QoS add/update/remove request and for | ||
69 | target/flags update. | ||
70 | |||
71 | pm_qos_add_request "pm_qos_class=%s value=%d" | ||
72 | pm_qos_update_request "pm_qos_class=%s value=%d" | ||
73 | pm_qos_remove_request "pm_qos_class=%s value=%d" | ||
74 | pm_qos_update_request_timeout "pm_qos_class=%s value=%d, timeout_us=%ld" | ||
75 | |||
76 | The first parameter gives the QoS class name (e.g. "CPU_DMA_LATENCY"). | ||
77 | The second parameter is value to be added/updated/removed. | ||
78 | The third parameter is timeout value in usec. | ||
79 | |||
80 | pm_qos_update_target "action=%s prev_value=%d curr_value=%d" | ||
81 | pm_qos_update_flags "action=%s prev_value=0x%x curr_value=0x%x" | ||
82 | |||
83 | The first parameter gives the QoS action name (e.g. "ADD_REQ"). | ||
84 | The second parameter is the previous QoS value. | ||
85 | The third parameter is the current QoS value to update. | ||
86 | |||
87 | And, there are also events used for device PM QoS add/update/remove request. | ||
88 | |||
89 | dev_pm_qos_add_request "device=%s type=%s new_value=%d" | ||
90 | dev_pm_qos_update_request "device=%s type=%s new_value=%d" | ||
91 | dev_pm_qos_remove_request "device=%s type=%s new_value=%d" | ||
92 | |||
93 | The first parameter gives the device name which tries to add/update/remove | ||
94 | QoS requests. | ||
95 | The second parameter gives the request type (e.g. "DEV_PM_QOS_LATENCY"). | ||
96 | The third parameter is value to be added/updated/removed. | ||
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index e6d230700b2b..e37feb2f05a3 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c | |||
@@ -591,11 +591,6 @@ static int _od_runtime_suspend(struct device *dev) | |||
591 | return ret; | 591 | return ret; |
592 | } | 592 | } |
593 | 593 | ||
594 | static int _od_runtime_idle(struct device *dev) | ||
595 | { | ||
596 | return pm_generic_runtime_idle(dev); | ||
597 | } | ||
598 | |||
599 | static int _od_runtime_resume(struct device *dev) | 594 | static int _od_runtime_resume(struct device *dev) |
600 | { | 595 | { |
601 | struct platform_device *pdev = to_platform_device(dev); | 596 | struct platform_device *pdev = to_platform_device(dev); |
@@ -653,7 +648,7 @@ static int _od_resume_noirq(struct device *dev) | |||
653 | struct dev_pm_domain omap_device_pm_domain = { | 648 | struct dev_pm_domain omap_device_pm_domain = { |
654 | .ops = { | 649 | .ops = { |
655 | SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume, | 650 | SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume, |
656 | _od_runtime_idle) | 651 | NULL) |
657 | USE_PLATFORM_PM_SLEEP_OPS | 652 | USE_PLATFORM_PM_SLEEP_OPS |
658 | .suspend_noirq = _od_suspend_noirq, | 653 | .suspend_noirq = _od_suspend_noirq, |
659 | .resume_noirq = _od_resume_noirq, | 654 | .resume_noirq = _od_resume_noirq, |
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 5f3597b87f27..67624d4d5aef 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c | |||
@@ -933,7 +933,6 @@ static struct dev_pm_domain acpi_general_pm_domain = { | |||
933 | #ifdef CONFIG_PM_RUNTIME | 933 | #ifdef CONFIG_PM_RUNTIME |
934 | .runtime_suspend = acpi_subsys_runtime_suspend, | 934 | .runtime_suspend = acpi_subsys_runtime_suspend, |
935 | .runtime_resume = acpi_subsys_runtime_resume, | 935 | .runtime_resume = acpi_subsys_runtime_resume, |
936 | .runtime_idle = pm_generic_runtime_idle, | ||
937 | #endif | 936 | #endif |
938 | #ifdef CONFIG_PM_SLEEP | 937 | #ifdef CONFIG_PM_SLEEP |
939 | .prepare = acpi_subsys_prepare, | 938 | .prepare = acpi_subsys_prepare, |
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index cdbad3a454a0..c6707278a6bb 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c | |||
@@ -284,7 +284,7 @@ static const struct dev_pm_ops amba_pm = { | |||
284 | SET_RUNTIME_PM_OPS( | 284 | SET_RUNTIME_PM_OPS( |
285 | amba_pm_runtime_suspend, | 285 | amba_pm_runtime_suspend, |
286 | amba_pm_runtime_resume, | 286 | amba_pm_runtime_resume, |
287 | pm_generic_runtime_idle | 287 | NULL |
288 | ) | 288 | ) |
289 | }; | 289 | }; |
290 | 290 | ||
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index adf002a3c584..6e458a40a93b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -5436,7 +5436,7 @@ static int ata_port_runtime_idle(struct device *dev) | |||
5436 | return -EBUSY; | 5436 | return -EBUSY; |
5437 | } | 5437 | } |
5438 | 5438 | ||
5439 | return pm_runtime_suspend(dev); | 5439 | return 0; |
5440 | } | 5440 | } |
5441 | 5441 | ||
5442 | static int ata_port_runtime_suspend(struct device *dev) | 5442 | static int ata_port_runtime_suspend(struct device *dev) |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 9eda84246ffd..96a930387ebc 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -888,7 +888,6 @@ int platform_pm_restore(struct device *dev) | |||
888 | static const struct dev_pm_ops platform_dev_pm_ops = { | 888 | static const struct dev_pm_ops platform_dev_pm_ops = { |
889 | .runtime_suspend = pm_generic_runtime_suspend, | 889 | .runtime_suspend = pm_generic_runtime_suspend, |
890 | .runtime_resume = pm_generic_runtime_resume, | 890 | .runtime_resume = pm_generic_runtime_resume, |
891 | .runtime_idle = pm_generic_runtime_idle, | ||
892 | USE_PLATFORM_PM_SLEEP_OPS | 891 | USE_PLATFORM_PM_SLEEP_OPS |
893 | }; | 892 | }; |
894 | 893 | ||
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 7072404c8b6d..bfb8955c406c 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
@@ -2143,7 +2143,6 @@ void pm_genpd_init(struct generic_pm_domain *genpd, | |||
2143 | genpd->max_off_time_changed = true; | 2143 | genpd->max_off_time_changed = true; |
2144 | genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend; | 2144 | genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend; |
2145 | genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume; | 2145 | genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume; |
2146 | genpd->domain.ops.runtime_idle = pm_generic_runtime_idle; | ||
2147 | genpd->domain.ops.prepare = pm_genpd_prepare; | 2146 | genpd->domain.ops.prepare = pm_genpd_prepare; |
2148 | genpd->domain.ops.suspend = pm_genpd_suspend; | 2147 | genpd->domain.ops.suspend = pm_genpd_suspend; |
2149 | genpd->domain.ops.suspend_late = pm_genpd_suspend_late; | 2148 | genpd->domain.ops.suspend_late = pm_genpd_suspend_late; |
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c index bfd898b8988e..5ee030a864f9 100644 --- a/drivers/base/power/generic_ops.c +++ b/drivers/base/power/generic_ops.c | |||
@@ -12,29 +12,6 @@ | |||
12 | 12 | ||
13 | #ifdef CONFIG_PM_RUNTIME | 13 | #ifdef CONFIG_PM_RUNTIME |
14 | /** | 14 | /** |
15 | * pm_generic_runtime_idle - Generic runtime idle callback for subsystems. | ||
16 | * @dev: Device to handle. | ||
17 | * | ||
18 | * If PM operations are defined for the @dev's driver and they include | ||
19 | * ->runtime_idle(), execute it and return its error code, if nonzero. | ||
20 | * Otherwise, execute pm_runtime_suspend() for the device and return 0. | ||
21 | */ | ||
22 | int pm_generic_runtime_idle(struct device *dev) | ||
23 | { | ||
24 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
25 | |||
26 | if (pm && pm->runtime_idle) { | ||
27 | int ret = pm->runtime_idle(dev); | ||
28 | if (ret) | ||
29 | return ret; | ||
30 | } | ||
31 | |||
32 | pm_runtime_suspend(dev); | ||
33 | return 0; | ||
34 | } | ||
35 | EXPORT_SYMBOL_GPL(pm_generic_runtime_idle); | ||
36 | |||
37 | /** | ||
38 | * pm_generic_runtime_suspend - Generic runtime suspend callback for subsystems. | 15 | * pm_generic_runtime_suspend - Generic runtime suspend callback for subsystems. |
39 | * @dev: Device to suspend. | 16 | * @dev: Device to suspend. |
40 | * | 17 | * |
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 71671c42ef45..5c1361a9e5dd 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/export.h> | 42 | #include <linux/export.h> |
43 | #include <linux/pm_runtime.h> | 43 | #include <linux/pm_runtime.h> |
44 | #include <linux/err.h> | 44 | #include <linux/err.h> |
45 | #include <trace/events/power.h> | ||
45 | 46 | ||
46 | #include "power.h" | 47 | #include "power.h" |
47 | 48 | ||
@@ -305,6 +306,7 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, | |||
305 | else if (!dev->power.qos) | 306 | else if (!dev->power.qos) |
306 | ret = dev_pm_qos_constraints_allocate(dev); | 307 | ret = dev_pm_qos_constraints_allocate(dev); |
307 | 308 | ||
309 | trace_dev_pm_qos_add_request(dev_name(dev), type, value); | ||
308 | if (!ret) { | 310 | if (!ret) { |
309 | req->dev = dev; | 311 | req->dev = dev; |
310 | req->type = type; | 312 | req->type = type; |
@@ -349,6 +351,8 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req, | |||
349 | return -EINVAL; | 351 | return -EINVAL; |
350 | } | 352 | } |
351 | 353 | ||
354 | trace_dev_pm_qos_update_request(dev_name(req->dev), req->type, | ||
355 | new_value); | ||
352 | if (curr_value != new_value) | 356 | if (curr_value != new_value) |
353 | ret = apply_constraint(req, PM_QOS_UPDATE_REQ, new_value); | 357 | ret = apply_constraint(req, PM_QOS_UPDATE_REQ, new_value); |
354 | 358 | ||
@@ -398,6 +402,8 @@ static int __dev_pm_qos_remove_request(struct dev_pm_qos_request *req) | |||
398 | if (IS_ERR_OR_NULL(req->dev->power.qos)) | 402 | if (IS_ERR_OR_NULL(req->dev->power.qos)) |
399 | return -ENODEV; | 403 | return -ENODEV; |
400 | 404 | ||
405 | trace_dev_pm_qos_remove_request(dev_name(req->dev), req->type, | ||
406 | PM_QOS_DEFAULT_VALUE); | ||
401 | ret = apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); | 407 | ret = apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); |
402 | memset(req, 0, sizeof(*req)); | 408 | memset(req, 0, sizeof(*req)); |
403 | return ret; | 409 | return ret; |
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index ef13ad08afb2..268a35097578 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -293,11 +293,8 @@ static int rpm_idle(struct device *dev, int rpmflags) | |||
293 | /* Pending requests need to be canceled. */ | 293 | /* Pending requests need to be canceled. */ |
294 | dev->power.request = RPM_REQ_NONE; | 294 | dev->power.request = RPM_REQ_NONE; |
295 | 295 | ||
296 | if (dev->power.no_callbacks) { | 296 | if (dev->power.no_callbacks) |
297 | /* Assume ->runtime_idle() callback would have suspended. */ | ||
298 | retval = rpm_suspend(dev, rpmflags); | ||
299 | goto out; | 297 | goto out; |
300 | } | ||
301 | 298 | ||
302 | /* Carry out an asynchronous or a synchronous idle notification. */ | 299 | /* Carry out an asynchronous or a synchronous idle notification. */ |
303 | if (rpmflags & RPM_ASYNC) { | 300 | if (rpmflags & RPM_ASYNC) { |
@@ -306,7 +303,8 @@ static int rpm_idle(struct device *dev, int rpmflags) | |||
306 | dev->power.request_pending = true; | 303 | dev->power.request_pending = true; |
307 | queue_work(pm_wq, &dev->power.work); | 304 | queue_work(pm_wq, &dev->power.work); |
308 | } | 305 | } |
309 | goto out; | 306 | trace_rpm_return_int(dev, _THIS_IP_, 0); |
307 | return 0; | ||
310 | } | 308 | } |
311 | 309 | ||
312 | dev->power.idle_notification = true; | 310 | dev->power.idle_notification = true; |
@@ -326,14 +324,14 @@ static int rpm_idle(struct device *dev, int rpmflags) | |||
326 | callback = dev->driver->pm->runtime_idle; | 324 | callback = dev->driver->pm->runtime_idle; |
327 | 325 | ||
328 | if (callback) | 326 | if (callback) |
329 | __rpm_callback(callback, dev); | 327 | retval = __rpm_callback(callback, dev); |
330 | 328 | ||
331 | dev->power.idle_notification = false; | 329 | dev->power.idle_notification = false; |
332 | wake_up_all(&dev->power.wait_queue); | 330 | wake_up_all(&dev->power.wait_queue); |
333 | 331 | ||
334 | out: | 332 | out: |
335 | trace_rpm_return_int(dev, _THIS_IP_, retval); | 333 | trace_rpm_return_int(dev, _THIS_IP_, retval); |
336 | return retval; | 334 | return retval ? retval : rpm_suspend(dev, rpmflags); |
337 | } | 335 | } |
338 | 336 | ||
339 | /** | 337 | /** |
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 79715e7fa43e..2d56f4113ae7 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c | |||
@@ -659,7 +659,7 @@ void pm_wakeup_event(struct device *dev, unsigned int msec) | |||
659 | } | 659 | } |
660 | EXPORT_SYMBOL_GPL(pm_wakeup_event); | 660 | EXPORT_SYMBOL_GPL(pm_wakeup_event); |
661 | 661 | ||
662 | static void print_active_wakeup_sources(void) | 662 | void pm_print_active_wakeup_sources(void) |
663 | { | 663 | { |
664 | struct wakeup_source *ws; | 664 | struct wakeup_source *ws; |
665 | int active = 0; | 665 | int active = 0; |
@@ -683,6 +683,7 @@ static void print_active_wakeup_sources(void) | |||
683 | last_activity_ws->name); | 683 | last_activity_ws->name); |
684 | rcu_read_unlock(); | 684 | rcu_read_unlock(); |
685 | } | 685 | } |
686 | EXPORT_SYMBOL_GPL(pm_print_active_wakeup_sources); | ||
686 | 687 | ||
687 | /** | 688 | /** |
688 | * pm_wakeup_pending - Check if power transition in progress should be aborted. | 689 | * pm_wakeup_pending - Check if power transition in progress should be aborted. |
@@ -707,8 +708,10 @@ bool pm_wakeup_pending(void) | |||
707 | } | 708 | } |
708 | spin_unlock_irqrestore(&events_lock, flags); | 709 | spin_unlock_irqrestore(&events_lock, flags); |
709 | 710 | ||
710 | if (ret) | 711 | if (ret) { |
711 | print_active_wakeup_sources(); | 712 | pr_info("PM: Wakeup pending, aborting suspend\n"); |
713 | pm_print_active_wakeup_sources(); | ||
714 | } | ||
712 | 715 | ||
713 | return ret; | 716 | return ret; |
714 | } | 717 | } |
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c index a0de82e21a7c..a975ebebea8a 100644 --- a/drivers/dma/intel_mid_dma.c +++ b/drivers/dma/intel_mid_dma.c | |||
@@ -1405,7 +1405,7 @@ static int dma_runtime_idle(struct device *dev) | |||
1405 | return -EAGAIN; | 1405 | return -EAGAIN; |
1406 | } | 1406 | } |
1407 | 1407 | ||
1408 | return pm_schedule_suspend(dev, 0); | 1408 | return 0; |
1409 | } | 1409 | } |
1410 | 1410 | ||
1411 | /****************************************************************************** | 1411 | /****************************************************************************** |
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c index 62ef10a641c4..89d0d2a3b1bb 100644 --- a/drivers/gpio/gpio-langwell.c +++ b/drivers/gpio/gpio-langwell.c | |||
@@ -305,11 +305,7 @@ static const struct irq_domain_ops lnw_gpio_irq_ops = { | |||
305 | 305 | ||
306 | static int lnw_gpio_runtime_idle(struct device *dev) | 306 | static int lnw_gpio_runtime_idle(struct device *dev) |
307 | { | 307 | { |
308 | int err = pm_schedule_suspend(dev, 500); | 308 | pm_schedule_suspend(dev, 500); |
309 | |||
310 | if (!err) | ||
311 | return 0; | ||
312 | |||
313 | return -EBUSY; | 309 | return -EBUSY; |
314 | } | 310 | } |
315 | 311 | ||
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 48e31ed69dbf..f32ca293ae0e 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -435,7 +435,7 @@ static const struct dev_pm_ops i2c_device_pm_ops = { | |||
435 | SET_RUNTIME_PM_OPS( | 435 | SET_RUNTIME_PM_OPS( |
436 | pm_generic_runtime_suspend, | 436 | pm_generic_runtime_suspend, |
437 | pm_generic_runtime_resume, | 437 | pm_generic_runtime_resume, |
438 | pm_generic_runtime_idle | 438 | NULL |
439 | ) | 439 | ) |
440 | }; | 440 | }; |
441 | 441 | ||
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 13f7866de46e..3598b0ecf8c7 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c | |||
@@ -886,12 +886,6 @@ static int ab8500_gpadc_runtime_resume(struct device *dev) | |||
886 | return ret; | 886 | return ret; |
887 | } | 887 | } |
888 | 888 | ||
889 | static int ab8500_gpadc_runtime_idle(struct device *dev) | ||
890 | { | ||
891 | pm_runtime_suspend(dev); | ||
892 | return 0; | ||
893 | } | ||
894 | |||
895 | static int ab8500_gpadc_suspend(struct device *dev) | 889 | static int ab8500_gpadc_suspend(struct device *dev) |
896 | { | 890 | { |
897 | struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); | 891 | struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); |
@@ -1039,7 +1033,7 @@ static int ab8500_gpadc_remove(struct platform_device *pdev) | |||
1039 | static const struct dev_pm_ops ab8500_gpadc_pm_ops = { | 1033 | static const struct dev_pm_ops ab8500_gpadc_pm_ops = { |
1040 | SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend, | 1034 | SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend, |
1041 | ab8500_gpadc_runtime_resume, | 1035 | ab8500_gpadc_runtime_resume, |
1042 | ab8500_gpadc_runtime_idle) | 1036 | NULL) |
1043 | SET_SYSTEM_SLEEP_PM_OPS(ab8500_gpadc_suspend, | 1037 | SET_SYSTEM_SLEEP_PM_OPS(ab8500_gpadc_suspend, |
1044 | ab8500_gpadc_resume) | 1038 | ab8500_gpadc_resume) |
1045 | 1039 | ||
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index e219c97a02a4..9d5c71125576 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
@@ -164,7 +164,7 @@ static int mmc_runtime_resume(struct device *dev) | |||
164 | 164 | ||
165 | static int mmc_runtime_idle(struct device *dev) | 165 | static int mmc_runtime_idle(struct device *dev) |
166 | { | 166 | { |
167 | return pm_runtime_suspend(dev); | 167 | return 0; |
168 | } | 168 | } |
169 | 169 | ||
170 | #endif /* !CONFIG_PM_RUNTIME */ | 170 | #endif /* !CONFIG_PM_RUNTIME */ |
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 546c67c2bbbf..6d67492a9247 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c | |||
@@ -211,7 +211,7 @@ static const struct dev_pm_ops sdio_bus_pm_ops = { | |||
211 | SET_RUNTIME_PM_OPS( | 211 | SET_RUNTIME_PM_OPS( |
212 | pm_generic_runtime_suspend, | 212 | pm_generic_runtime_suspend, |
213 | pm_generic_runtime_resume, | 213 | pm_generic_runtime_resume, |
214 | pm_generic_runtime_idle | 214 | NULL |
215 | ) | 215 | ) |
216 | }; | 216 | }; |
217 | 217 | ||
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 79277fb36c6b..e6515e21afa3 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -1050,26 +1050,22 @@ static int pci_pm_runtime_idle(struct device *dev) | |||
1050 | { | 1050 | { |
1051 | struct pci_dev *pci_dev = to_pci_dev(dev); | 1051 | struct pci_dev *pci_dev = to_pci_dev(dev); |
1052 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 1052 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
1053 | int ret = 0; | ||
1053 | 1054 | ||
1054 | /* | 1055 | /* |
1055 | * If pci_dev->driver is not set (unbound), the device should | 1056 | * If pci_dev->driver is not set (unbound), the device should |
1056 | * always remain in D0 regardless of the runtime PM status | 1057 | * always remain in D0 regardless of the runtime PM status |
1057 | */ | 1058 | */ |
1058 | if (!pci_dev->driver) | 1059 | if (!pci_dev->driver) |
1059 | goto out; | 1060 | return 0; |
1060 | 1061 | ||
1061 | if (!pm) | 1062 | if (!pm) |
1062 | return -ENOSYS; | 1063 | return -ENOSYS; |
1063 | 1064 | ||
1064 | if (pm->runtime_idle) { | 1065 | if (pm->runtime_idle) |
1065 | int ret = pm->runtime_idle(dev); | 1066 | ret = pm->runtime_idle(dev); |
1066 | if (ret) | ||
1067 | return ret; | ||
1068 | } | ||
1069 | 1067 | ||
1070 | out: | 1068 | return ret; |
1071 | pm_runtime_suspend(dev); | ||
1072 | return 0; | ||
1073 | } | 1069 | } |
1074 | 1070 | ||
1075 | #else /* !CONFIG_PM_RUNTIME */ | 1071 | #else /* !CONFIG_PM_RUNTIME */ |
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index 42539ee2cb11..4c5aabe21755 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c | |||
@@ -229,8 +229,6 @@ static int scsi_runtime_resume(struct device *dev) | |||
229 | 229 | ||
230 | static int scsi_runtime_idle(struct device *dev) | 230 | static int scsi_runtime_idle(struct device *dev) |
231 | { | 231 | { |
232 | int err; | ||
233 | |||
234 | dev_dbg(dev, "scsi_runtime_idle\n"); | 232 | dev_dbg(dev, "scsi_runtime_idle\n"); |
235 | 233 | ||
236 | /* Insert hooks here for targets, hosts, and transport classes */ | 234 | /* Insert hooks here for targets, hosts, and transport classes */ |
@@ -240,14 +238,11 @@ static int scsi_runtime_idle(struct device *dev) | |||
240 | 238 | ||
241 | if (sdev->request_queue->dev) { | 239 | if (sdev->request_queue->dev) { |
242 | pm_runtime_mark_last_busy(dev); | 240 | pm_runtime_mark_last_busy(dev); |
243 | err = pm_runtime_autosuspend(dev); | 241 | pm_runtime_autosuspend(dev); |
244 | } else { | 242 | return -EBUSY; |
245 | err = pm_runtime_suspend(dev); | ||
246 | } | 243 | } |
247 | } else { | ||
248 | err = pm_runtime_suspend(dev); | ||
249 | } | 244 | } |
250 | return err; | 245 | return 0; |
251 | } | 246 | } |
252 | 247 | ||
253 | int scsi_autopm_get_device(struct scsi_device *sdev) | 248 | int scsi_autopm_get_device(struct scsi_device *sdev) |
diff --git a/drivers/sh/pm_runtime.c b/drivers/sh/pm_runtime.c index afe9282629b9..8afa5a4589f2 100644 --- a/drivers/sh/pm_runtime.c +++ b/drivers/sh/pm_runtime.c | |||
@@ -25,7 +25,7 @@ | |||
25 | static int default_platform_runtime_idle(struct device *dev) | 25 | static int default_platform_runtime_idle(struct device *dev) |
26 | { | 26 | { |
27 | /* suspend synchronously to disable clocks immediately */ | 27 | /* suspend synchronously to disable clocks immediately */ |
28 | return pm_runtime_suspend(dev); | 28 | return 0; |
29 | } | 29 | } |
30 | 30 | ||
31 | static struct dev_pm_domain default_pm_domain = { | 31 | static struct dev_pm_domain default_pm_domain = { |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 32b7bb111eb6..095cfaded1c0 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -223,7 +223,7 @@ static const struct dev_pm_ops spi_pm = { | |||
223 | SET_RUNTIME_PM_OPS( | 223 | SET_RUNTIME_PM_OPS( |
224 | pm_generic_runtime_suspend, | 224 | pm_generic_runtime_suspend, |
225 | pm_generic_runtime_resume, | 225 | pm_generic_runtime_resume, |
226 | pm_generic_runtime_idle | 226 | NULL |
227 | ) | 227 | ) |
228 | }; | 228 | }; |
229 | 229 | ||
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index 5f4765a7a5c5..5dfcf3bae23a 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c | |||
@@ -1248,13 +1248,8 @@ static int serial_hsu_resume(struct pci_dev *pdev) | |||
1248 | #ifdef CONFIG_PM_RUNTIME | 1248 | #ifdef CONFIG_PM_RUNTIME |
1249 | static int serial_hsu_runtime_idle(struct device *dev) | 1249 | static int serial_hsu_runtime_idle(struct device *dev) |
1250 | { | 1250 | { |
1251 | int err; | 1251 | pm_schedule_suspend(dev, 500); |
1252 | 1252 | return -EBUSY; | |
1253 | err = pm_schedule_suspend(dev, 500); | ||
1254 | if (err) | ||
1255 | return -EBUSY; | ||
1256 | |||
1257 | return 0; | ||
1258 | } | 1253 | } |
1259 | 1254 | ||
1260 | static int serial_hsu_runtime_suspend(struct device *dev) | 1255 | static int serial_hsu_runtime_suspend(struct device *dev) |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 6eab440e1542..7609ac4aed1c 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -1765,7 +1765,8 @@ int usb_runtime_idle(struct device *dev) | |||
1765 | */ | 1765 | */ |
1766 | if (autosuspend_check(udev) == 0) | 1766 | if (autosuspend_check(udev) == 0) |
1767 | pm_runtime_autosuspend(dev); | 1767 | pm_runtime_autosuspend(dev); |
1768 | return 0; | 1768 | /* Tell the core not to suspend it, though. */ |
1769 | return -EBUSY; | ||
1769 | } | 1770 | } |
1770 | 1771 | ||
1771 | int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) | 1772 | int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) |
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index b8bad294eeb8..8c1b2c509467 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c | |||
@@ -141,7 +141,6 @@ static const struct dev_pm_ops usb_port_pm_ops = { | |||
141 | #ifdef CONFIG_PM_RUNTIME | 141 | #ifdef CONFIG_PM_RUNTIME |
142 | .runtime_suspend = usb_port_runtime_suspend, | 142 | .runtime_suspend = usb_port_runtime_suspend, |
143 | .runtime_resume = usb_port_runtime_resume, | 143 | .runtime_resume = usb_port_runtime_resume, |
144 | .runtime_idle = pm_generic_runtime_idle, | ||
145 | #endif | 144 | #endif |
146 | }; | 145 | }; |
147 | 146 | ||
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 7d7e09efff9b..6fa7cea25da9 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h | |||
@@ -37,7 +37,6 @@ extern void pm_runtime_enable(struct device *dev); | |||
37 | extern void __pm_runtime_disable(struct device *dev, bool check_resume); | 37 | extern void __pm_runtime_disable(struct device *dev, bool check_resume); |
38 | extern void pm_runtime_allow(struct device *dev); | 38 | extern void pm_runtime_allow(struct device *dev); |
39 | extern void pm_runtime_forbid(struct device *dev); | 39 | extern void pm_runtime_forbid(struct device *dev); |
40 | extern int pm_generic_runtime_idle(struct device *dev); | ||
41 | extern int pm_generic_runtime_suspend(struct device *dev); | 40 | extern int pm_generic_runtime_suspend(struct device *dev); |
42 | extern int pm_generic_runtime_resume(struct device *dev); | 41 | extern int pm_generic_runtime_resume(struct device *dev); |
43 | extern void pm_runtime_no_callbacks(struct device *dev); | 42 | extern void pm_runtime_no_callbacks(struct device *dev); |
@@ -143,7 +142,6 @@ static inline bool pm_runtime_active(struct device *dev) { return true; } | |||
143 | static inline bool pm_runtime_status_suspended(struct device *dev) { return false; } | 142 | static inline bool pm_runtime_status_suspended(struct device *dev) { return false; } |
144 | static inline bool pm_runtime_enabled(struct device *dev) { return false; } | 143 | static inline bool pm_runtime_enabled(struct device *dev) { return false; } |
145 | 144 | ||
146 | static inline int pm_generic_runtime_idle(struct device *dev) { return 0; } | ||
147 | static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; } | 145 | static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; } |
148 | static inline int pm_generic_runtime_resume(struct device *dev) { return 0; } | 146 | static inline int pm_generic_runtime_resume(struct device *dev) { return 0; } |
149 | static inline void pm_runtime_no_callbacks(struct device *dev) {} | 147 | static inline void pm_runtime_no_callbacks(struct device *dev) {} |
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index d4e3f16d5e89..f73cabf59012 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
@@ -363,6 +363,7 @@ extern bool pm_wakeup_pending(void); | |||
363 | extern bool pm_get_wakeup_count(unsigned int *count, bool block); | 363 | extern bool pm_get_wakeup_count(unsigned int *count, bool block); |
364 | extern bool pm_save_wakeup_count(unsigned int count); | 364 | extern bool pm_save_wakeup_count(unsigned int count); |
365 | extern void pm_wakep_autosleep_enabled(bool set); | 365 | extern void pm_wakep_autosleep_enabled(bool set); |
366 | extern void pm_print_active_wakeup_sources(void); | ||
366 | 367 | ||
367 | static inline void lock_system_sleep(void) | 368 | static inline void lock_system_sleep(void) |
368 | { | 369 | { |
diff --git a/include/trace/events/power.h b/include/trace/events/power.h index 427acab5d69a..8e42410bd159 100644 --- a/include/trace/events/power.h +++ b/include/trace/events/power.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #define _TRACE_POWER_H | 5 | #define _TRACE_POWER_H |
6 | 6 | ||
7 | #include <linux/ktime.h> | 7 | #include <linux/ktime.h> |
8 | #include <linux/pm_qos.h> | ||
8 | #include <linux/tracepoint.h> | 9 | #include <linux/tracepoint.h> |
9 | 10 | ||
10 | DECLARE_EVENT_CLASS(cpu, | 11 | DECLARE_EVENT_CLASS(cpu, |
@@ -177,6 +178,178 @@ DEFINE_EVENT(power_domain, power_domain_target, | |||
177 | 178 | ||
178 | TP_ARGS(name, state, cpu_id) | 179 | TP_ARGS(name, state, cpu_id) |
179 | ); | 180 | ); |
181 | |||
182 | /* | ||
183 | * The pm qos events are used for pm qos update | ||
184 | */ | ||
185 | DECLARE_EVENT_CLASS(pm_qos_request, | ||
186 | |||
187 | TP_PROTO(int pm_qos_class, s32 value), | ||
188 | |||
189 | TP_ARGS(pm_qos_class, value), | ||
190 | |||
191 | TP_STRUCT__entry( | ||
192 | __field( int, pm_qos_class ) | ||
193 | __field( s32, value ) | ||
194 | ), | ||
195 | |||
196 | TP_fast_assign( | ||
197 | __entry->pm_qos_class = pm_qos_class; | ||
198 | __entry->value = value; | ||
199 | ), | ||
200 | |||
201 | TP_printk("pm_qos_class=%s value=%d", | ||
202 | __print_symbolic(__entry->pm_qos_class, | ||
203 | { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }, | ||
204 | { PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" }, | ||
205 | { PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }), | ||
206 | __entry->value) | ||
207 | ); | ||
208 | |||
209 | DEFINE_EVENT(pm_qos_request, pm_qos_add_request, | ||
210 | |||
211 | TP_PROTO(int pm_qos_class, s32 value), | ||
212 | |||
213 | TP_ARGS(pm_qos_class, value) | ||
214 | ); | ||
215 | |||
216 | DEFINE_EVENT(pm_qos_request, pm_qos_update_request, | ||
217 | |||
218 | TP_PROTO(int pm_qos_class, s32 value), | ||
219 | |||
220 | TP_ARGS(pm_qos_class, value) | ||
221 | ); | ||
222 | |||
223 | DEFINE_EVENT(pm_qos_request, pm_qos_remove_request, | ||
224 | |||
225 | TP_PROTO(int pm_qos_class, s32 value), | ||
226 | |||
227 | TP_ARGS(pm_qos_class, value) | ||
228 | ); | ||
229 | |||
230 | TRACE_EVENT(pm_qos_update_request_timeout, | ||
231 | |||
232 | TP_PROTO(int pm_qos_class, s32 value, unsigned long timeout_us), | ||
233 | |||
234 | TP_ARGS(pm_qos_class, value, timeout_us), | ||
235 | |||
236 | TP_STRUCT__entry( | ||
237 | __field( int, pm_qos_class ) | ||
238 | __field( s32, value ) | ||
239 | __field( unsigned long, timeout_us ) | ||
240 | ), | ||
241 | |||
242 | TP_fast_assign( | ||
243 | __entry->pm_qos_class = pm_qos_class; | ||
244 | __entry->value = value; | ||
245 | __entry->timeout_us = timeout_us; | ||
246 | ), | ||
247 | |||
248 | TP_printk("pm_qos_class=%s value=%d, timeout_us=%ld", | ||
249 | __print_symbolic(__entry->pm_qos_class, | ||
250 | { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }, | ||
251 | { PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" }, | ||
252 | { PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }), | ||
253 | __entry->value, __entry->timeout_us) | ||
254 | ); | ||
255 | |||
256 | DECLARE_EVENT_CLASS(pm_qos_update, | ||
257 | |||
258 | TP_PROTO(enum pm_qos_req_action action, int prev_value, int curr_value), | ||
259 | |||
260 | TP_ARGS(action, prev_value, curr_value), | ||
261 | |||
262 | TP_STRUCT__entry( | ||
263 | __field( enum pm_qos_req_action, action ) | ||
264 | __field( int, prev_value ) | ||
265 | __field( int, curr_value ) | ||
266 | ), | ||
267 | |||
268 | TP_fast_assign( | ||
269 | __entry->action = action; | ||
270 | __entry->prev_value = prev_value; | ||
271 | __entry->curr_value = curr_value; | ||
272 | ), | ||
273 | |||
274 | TP_printk("action=%s prev_value=%d curr_value=%d", | ||
275 | __print_symbolic(__entry->action, | ||
276 | { PM_QOS_ADD_REQ, "ADD_REQ" }, | ||
277 | { PM_QOS_UPDATE_REQ, "UPDATE_REQ" }, | ||
278 | { PM_QOS_REMOVE_REQ, "REMOVE_REQ" }), | ||
279 | __entry->prev_value, __entry->curr_value) | ||
280 | ); | ||
281 | |||
282 | DEFINE_EVENT(pm_qos_update, pm_qos_update_target, | ||
283 | |||
284 | TP_PROTO(enum pm_qos_req_action action, int prev_value, int curr_value), | ||
285 | |||
286 | TP_ARGS(action, prev_value, curr_value) | ||
287 | ); | ||
288 | |||
289 | DEFINE_EVENT_PRINT(pm_qos_update, pm_qos_update_flags, | ||
290 | |||
291 | TP_PROTO(enum pm_qos_req_action action, int prev_value, int curr_value), | ||
292 | |||
293 | TP_ARGS(action, prev_value, curr_value), | ||
294 | |||
295 | TP_printk("action=%s prev_value=0x%x curr_value=0x%x", | ||
296 | __print_symbolic(__entry->action, | ||
297 | { PM_QOS_ADD_REQ, "ADD_REQ" }, | ||
298 | { PM_QOS_UPDATE_REQ, "UPDATE_REQ" }, | ||
299 | { PM_QOS_REMOVE_REQ, "REMOVE_REQ" }), | ||
300 | __entry->prev_value, __entry->curr_value) | ||
301 | ); | ||
302 | |||
303 | DECLARE_EVENT_CLASS(dev_pm_qos_request, | ||
304 | |||
305 | TP_PROTO(const char *name, enum dev_pm_qos_req_type type, | ||
306 | s32 new_value), | ||
307 | |||
308 | TP_ARGS(name, type, new_value), | ||
309 | |||
310 | TP_STRUCT__entry( | ||
311 | __string( name, name ) | ||
312 | __field( enum dev_pm_qos_req_type, type ) | ||
313 | __field( s32, new_value ) | ||
314 | ), | ||
315 | |||
316 | TP_fast_assign( | ||
317 | __assign_str(name, name); | ||
318 | __entry->type = type; | ||
319 | __entry->new_value = new_value; | ||
320 | ), | ||
321 | |||
322 | TP_printk("device=%s type=%s new_value=%d", | ||
323 | __get_str(name), | ||
324 | __print_symbolic(__entry->type, | ||
325 | { DEV_PM_QOS_LATENCY, "DEV_PM_QOS_LATENCY" }, | ||
326 | { DEV_PM_QOS_FLAGS, "DEV_PM_QOS_FLAGS" }), | ||
327 | __entry->new_value) | ||
328 | ); | ||
329 | |||
330 | DEFINE_EVENT(dev_pm_qos_request, dev_pm_qos_add_request, | ||
331 | |||
332 | TP_PROTO(const char *name, enum dev_pm_qos_req_type type, | ||
333 | s32 new_value), | ||
334 | |||
335 | TP_ARGS(name, type, new_value) | ||
336 | ); | ||
337 | |||
338 | DEFINE_EVENT(dev_pm_qos_request, dev_pm_qos_update_request, | ||
339 | |||
340 | TP_PROTO(const char *name, enum dev_pm_qos_req_type type, | ||
341 | s32 new_value), | ||
342 | |||
343 | TP_ARGS(name, type, new_value) | ||
344 | ); | ||
345 | |||
346 | DEFINE_EVENT(dev_pm_qos_request, dev_pm_qos_remove_request, | ||
347 | |||
348 | TP_PROTO(const char *name, enum dev_pm_qos_req_type type, | ||
349 | s32 new_value), | ||
350 | |||
351 | TP_ARGS(name, type, new_value) | ||
352 | ); | ||
180 | #endif /* _TRACE_POWER_H */ | 353 | #endif /* _TRACE_POWER_H */ |
181 | 354 | ||
182 | /* This part must be outside protection */ | 355 | /* This part must be outside protection */ |
diff --git a/kernel/power/main.c b/kernel/power/main.c index d77663bfedeb..0828070d38b4 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
@@ -424,6 +424,8 @@ static ssize_t wakeup_count_store(struct kobject *kobj, | |||
424 | if (sscanf(buf, "%u", &val) == 1) { | 424 | if (sscanf(buf, "%u", &val) == 1) { |
425 | if (pm_save_wakeup_count(val)) | 425 | if (pm_save_wakeup_count(val)) |
426 | error = n; | 426 | error = n; |
427 | else | ||
428 | pm_print_active_wakeup_sources(); | ||
427 | } | 429 | } |
428 | 430 | ||
429 | out: | 431 | out: |
diff --git a/kernel/power/qos.c b/kernel/power/qos.c index 587dddeebf15..06fe28589e9c 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c | |||
@@ -44,6 +44,7 @@ | |||
44 | 44 | ||
45 | #include <linux/uaccess.h> | 45 | #include <linux/uaccess.h> |
46 | #include <linux/export.h> | 46 | #include <linux/export.h> |
47 | #include <trace/events/power.h> | ||
47 | 48 | ||
48 | /* | 49 | /* |
49 | * locking rule: all changes to constraints or notifiers lists | 50 | * locking rule: all changes to constraints or notifiers lists |
@@ -202,6 +203,7 @@ int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node, | |||
202 | 203 | ||
203 | spin_unlock_irqrestore(&pm_qos_lock, flags); | 204 | spin_unlock_irqrestore(&pm_qos_lock, flags); |
204 | 205 | ||
206 | trace_pm_qos_update_target(action, prev_value, curr_value); | ||
205 | if (prev_value != curr_value) { | 207 | if (prev_value != curr_value) { |
206 | blocking_notifier_call_chain(c->notifiers, | 208 | blocking_notifier_call_chain(c->notifiers, |
207 | (unsigned long)curr_value, | 209 | (unsigned long)curr_value, |
@@ -272,6 +274,7 @@ bool pm_qos_update_flags(struct pm_qos_flags *pqf, | |||
272 | 274 | ||
273 | spin_unlock_irqrestore(&pm_qos_lock, irqflags); | 275 | spin_unlock_irqrestore(&pm_qos_lock, irqflags); |
274 | 276 | ||
277 | trace_pm_qos_update_flags(action, prev_value, curr_value); | ||
275 | return prev_value != curr_value; | 278 | return prev_value != curr_value; |
276 | } | 279 | } |
277 | 280 | ||
@@ -333,6 +336,7 @@ void pm_qos_add_request(struct pm_qos_request *req, | |||
333 | } | 336 | } |
334 | req->pm_qos_class = pm_qos_class; | 337 | req->pm_qos_class = pm_qos_class; |
335 | INIT_DELAYED_WORK(&req->work, pm_qos_work_fn); | 338 | INIT_DELAYED_WORK(&req->work, pm_qos_work_fn); |
339 | trace_pm_qos_add_request(pm_qos_class, value); | ||
336 | pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints, | 340 | pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints, |
337 | &req->node, PM_QOS_ADD_REQ, value); | 341 | &req->node, PM_QOS_ADD_REQ, value); |
338 | } | 342 | } |
@@ -361,6 +365,7 @@ void pm_qos_update_request(struct pm_qos_request *req, | |||
361 | 365 | ||
362 | cancel_delayed_work_sync(&req->work); | 366 | cancel_delayed_work_sync(&req->work); |
363 | 367 | ||
368 | trace_pm_qos_update_request(req->pm_qos_class, new_value); | ||
364 | if (new_value != req->node.prio) | 369 | if (new_value != req->node.prio) |
365 | pm_qos_update_target( | 370 | pm_qos_update_target( |
366 | pm_qos_array[req->pm_qos_class]->constraints, | 371 | pm_qos_array[req->pm_qos_class]->constraints, |
@@ -387,6 +392,8 @@ void pm_qos_update_request_timeout(struct pm_qos_request *req, s32 new_value, | |||
387 | 392 | ||
388 | cancel_delayed_work_sync(&req->work); | 393 | cancel_delayed_work_sync(&req->work); |
389 | 394 | ||
395 | trace_pm_qos_update_request_timeout(req->pm_qos_class, | ||
396 | new_value, timeout_us); | ||
390 | if (new_value != req->node.prio) | 397 | if (new_value != req->node.prio) |
391 | pm_qos_update_target( | 398 | pm_qos_update_target( |
392 | pm_qos_array[req->pm_qos_class]->constraints, | 399 | pm_qos_array[req->pm_qos_class]->constraints, |
@@ -416,6 +423,7 @@ void pm_qos_remove_request(struct pm_qos_request *req) | |||
416 | 423 | ||
417 | cancel_delayed_work_sync(&req->work); | 424 | cancel_delayed_work_sync(&req->work); |
418 | 425 | ||
426 | trace_pm_qos_remove_request(req->pm_qos_class, PM_QOS_DEFAULT_VALUE); | ||
419 | pm_qos_update_target(pm_qos_array[req->pm_qos_class]->constraints, | 427 | pm_qos_update_target(pm_qos_array[req->pm_qos_class]->constraints, |
420 | &req->node, PM_QOS_REMOVE_REQ, | 428 | &req->node, PM_QOS_REMOVE_REQ, |
421 | PM_QOS_DEFAULT_VALUE); | 429 | PM_QOS_DEFAULT_VALUE); |
@@ -477,7 +485,7 @@ static int find_pm_qos_object_by_minor(int minor) | |||
477 | { | 485 | { |
478 | int pm_qos_class; | 486 | int pm_qos_class; |
479 | 487 | ||
480 | for (pm_qos_class = 0; | 488 | for (pm_qos_class = PM_QOS_CPU_DMA_LATENCY; |
481 | pm_qos_class < PM_QOS_NUM_CLASSES; pm_qos_class++) { | 489 | pm_qos_class < PM_QOS_NUM_CLASSES; pm_qos_class++) { |
482 | if (minor == | 490 | if (minor == |
483 | pm_qos_array[pm_qos_class]->pm_qos_power_miscdev.minor) | 491 | pm_qos_array[pm_qos_class]->pm_qos_power_miscdev.minor) |
@@ -491,7 +499,7 @@ static int pm_qos_power_open(struct inode *inode, struct file *filp) | |||
491 | long pm_qos_class; | 499 | long pm_qos_class; |
492 | 500 | ||
493 | pm_qos_class = find_pm_qos_object_by_minor(iminor(inode)); | 501 | pm_qos_class = find_pm_qos_object_by_minor(iminor(inode)); |
494 | if (pm_qos_class >= 0) { | 502 | if (pm_qos_class >= PM_QOS_CPU_DMA_LATENCY) { |
495 | struct pm_qos_request *req = kzalloc(sizeof(*req), GFP_KERNEL); | 503 | struct pm_qos_request *req = kzalloc(sizeof(*req), GFP_KERNEL); |
496 | if (!req) | 504 | if (!req) |
497 | return -ENOMEM; | 505 | return -ENOMEM; |
@@ -584,7 +592,7 @@ static int __init pm_qos_power_init(void) | |||
584 | 592 | ||
585 | BUILD_BUG_ON(ARRAY_SIZE(pm_qos_array) != PM_QOS_NUM_CLASSES); | 593 | BUILD_BUG_ON(ARRAY_SIZE(pm_qos_array) != PM_QOS_NUM_CLASSES); |
586 | 594 | ||
587 | for (i = 1; i < PM_QOS_NUM_CLASSES; i++) { | 595 | for (i = PM_QOS_CPU_DMA_LATENCY; i < PM_QOS_NUM_CLASSES; i++) { |
588 | ret = register_pm_qos_misc(pm_qos_array[i]); | 596 | ret = register_pm_qos_misc(pm_qos_array[i]); |
589 | if (ret < 0) { | 597 | if (ret < 0) { |
590 | printk(KERN_ERR "pm_qos_param: %s setup failed\n", | 598 | printk(KERN_ERR "pm_qos_param: %s setup failed\n", |
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 0de28576807d..7872a35eafe7 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -642,8 +642,9 @@ __register_nosave_region(unsigned long start_pfn, unsigned long end_pfn, | |||
642 | region->end_pfn = end_pfn; | 642 | region->end_pfn = end_pfn; |
643 | list_add_tail(®ion->list, &nosave_regions); | 643 | list_add_tail(®ion->list, &nosave_regions); |
644 | Report: | 644 | Report: |
645 | printk(KERN_INFO "PM: Registered nosave memory: %016lx - %016lx\n", | 645 | printk(KERN_INFO "PM: Registered nosave memory: [mem %#010llx-%#010llx]\n", |
646 | start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT); | 646 | (unsigned long long) start_pfn << PAGE_SHIFT, |
647 | ((unsigned long long) end_pfn << PAGE_SHIFT) - 1); | ||
647 | } | 648 | } |
648 | 649 | ||
649 | /* | 650 | /* |
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index bef86d121eb2..ece04223bb1e 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c | |||
@@ -269,7 +269,7 @@ int suspend_devices_and_enter(suspend_state_t state) | |||
269 | suspend_test_start(); | 269 | suspend_test_start(); |
270 | error = dpm_suspend_start(PMSG_SUSPEND); | 270 | error = dpm_suspend_start(PMSG_SUSPEND); |
271 | if (error) { | 271 | if (error) { |
272 | printk(KERN_ERR "PM: Some devices failed to suspend\n"); | 272 | pr_err("PM: Some devices failed to suspend, or early wake event detected\n"); |
273 | goto Recover_platform; | 273 | goto Recover_platform; |
274 | } | 274 | } |
275 | suspend_test_finish("suspend devices"); | 275 | suspend_test_finish("suspend devices"); |