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
This commit is contained in:
Rafael J. Wysocki 2013-06-28 13:01:40 +02:00
commit e52cff8bdd
33 changed files with 315 additions and 113 deletions

View File

@ -7,7 +7,7 @@ one of the parameters.
Two different PM QoS frameworks are available:
1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput.
2. the per-device PM QoS framework provides the API to manage the per-device latency
constraints.
constraints and PM QoS flags.
Each parameters have defined units:
* latency: usec
@ -86,13 +86,17 @@ To remove the user mode request for a target value simply close the device
node.
2. PM QoS per-device latency framework
2. PM QoS per-device latency and flags framework
For each device, there are two lists of PM QoS requests. One is maintained
along with the aggregated target of latency value and the other is for PM QoS
flags. Values are updated in response to changes of the request list.
Target latency value is simply the minimum of the request values held in the
parameter list elements. The PM QoS flags aggregate value is a gather (bitwise
OR) of all list elements' values. Two device PM QoS flags are defined currently:
PM_QOS_FLAG_NO_POWER_OFF and PM_QOS_FLAG_REMOTE_WAKEUP.
For each device a list of performance requests is maintained along with
an aggregated target value. The aggregated target value is updated with
changes to the request list or elements of the list. Typically the
aggregated target value is simply the max or min of the request values held
in the parameter list elements.
Note: the aggregated target value is implemented as an atomic variable so that
reading the aggregated value does not require any locking mechanism.
@ -119,6 +123,38 @@ the request.
s32 dev_pm_qos_read_value(device):
Returns the aggregated value for a given device's constraints list.
enum pm_qos_flags_status dev_pm_qos_flags(device, mask)
Check PM QoS flags of the given device against the given mask of flags.
The meaning of the return values is as follows:
PM_QOS_FLAGS_ALL: All flags from the mask are set
PM_QOS_FLAGS_SOME: Some flags from the mask are set
PM_QOS_FLAGS_NONE: No flags from the mask are set
PM_QOS_FLAGS_UNDEFINED: The device's PM QoS structure has not been
initialized or the list of requests is empty.
int dev_pm_qos_add_ancestor_request(dev, handle, value)
Add a PM QoS request for the first direct ancestor of the given device whose
power.ignore_children flag is unset.
int dev_pm_qos_expose_latency_limit(device, value)
Add a request to the device's PM QoS list of latency constraints and create
a sysfs attribute pm_qos_resume_latency_us under the device's power directory
allowing user space to manipulate that request.
void dev_pm_qos_hide_latency_limit(device)
Drop the request added by dev_pm_qos_expose_latency_limit() from the device's
PM QoS list of latency constraints and remove sysfs attribute pm_qos_resume_latency_us
from the device's power directory.
int dev_pm_qos_expose_flags(device, value)
Add a request to the device's PM QoS list of flags and create sysfs attributes
pm_qos_no_power_off and pm_qos_remote_wakeup under the device's power directory
allowing user space to change these flags' value.
void dev_pm_qos_hide_flags(device)
Drop the request added by dev_pm_qos_expose_flags() from the device's PM QoS list
of flags and remove sysfs attributes pm_qos_no_power_off and pm_qos_remote_wakeup
under the device's power directory.
Notification mechanisms:
The per-device PM QoS framework has 2 different and distinct notification trees:

View File

@ -144,8 +144,12 @@ The action performed by the idle callback is totally dependent on the subsystem
(or driver) in question, but the expected and recommended action is to check
if the device can be suspended (i.e. if all of the conditions necessary for
suspending the device are satisfied) and to queue up a suspend request for the
device in that case. The value returned by this callback is ignored by the PM
core.
device in that case. If there is no idle callback, or if the callback returns
0, then the PM core will attempt to carry out a runtime suspend of the device;
in essence, it will call pm_runtime_suspend() directly. To prevent this (for
example, if the callback routine has started a delayed suspend), the routine
should return a non-zero value. Negative error return codes are ignored by the
PM core.
The helper functions provided by the PM core, described in Section 4, guarantee
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:
removing the device from device hierarchy
int pm_runtime_idle(struct device *dev);
- execute the subsystem-level idle callback for the device; returns 0 on
success or error code on failure, where -EINPROGRESS means that
->runtime_idle() is already being executed
- execute the subsystem-level idle callback for the device; returns an
error code on failure, where -EINPROGRESS means that ->runtime_idle() is
already being executed; if there is no callback or the callback returns 0
then run pm_runtime_suspend(dev) and return its result
int pm_runtime_suspend(struct device *dev);
- 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
management callbacks provided by the PM core, defined in
driver/base/power/generic_ops.c:
int pm_generic_runtime_idle(struct device *dev);
- invoke the ->runtime_idle() callback provided by the driver of this
device, if defined, and call pm_runtime_suspend() for this device if the
return value is 0 or the callback is not defined
int pm_generic_runtime_suspend(struct device *dev);
- invoke the ->runtime_suspend() callback provided by the driver of this
device and return its result, or return -EINVAL if not defined

View File

@ -63,3 +63,34 @@ power_domain_target "%s state=%lu cpu_id=%lu"
The first parameter gives the power domain name (e.g. "mpu_pwrdm").
The second parameter is the power domain target state.
4. PM QoS events
================
The PM QoS events are used for QoS add/update/remove request and for
target/flags update.
pm_qos_add_request "pm_qos_class=%s value=%d"
pm_qos_update_request "pm_qos_class=%s value=%d"
pm_qos_remove_request "pm_qos_class=%s value=%d"
pm_qos_update_request_timeout "pm_qos_class=%s value=%d, timeout_us=%ld"
The first parameter gives the QoS class name (e.g. "CPU_DMA_LATENCY").
The second parameter is value to be added/updated/removed.
The third parameter is timeout value in usec.
pm_qos_update_target "action=%s prev_value=%d curr_value=%d"
pm_qos_update_flags "action=%s prev_value=0x%x curr_value=0x%x"
The first parameter gives the QoS action name (e.g. "ADD_REQ").
The second parameter is the previous QoS value.
The third parameter is the current QoS value to update.
And, there are also events used for device PM QoS add/update/remove request.
dev_pm_qos_add_request "device=%s type=%s new_value=%d"
dev_pm_qos_update_request "device=%s type=%s new_value=%d"
dev_pm_qos_remove_request "device=%s type=%s new_value=%d"
The first parameter gives the device name which tries to add/update/remove
QoS requests.
The second parameter gives the request type (e.g. "DEV_PM_QOS_LATENCY").
The third parameter is value to be added/updated/removed.

View File

@ -591,11 +591,6 @@ static int _od_runtime_suspend(struct device *dev)
return ret;
}
static int _od_runtime_idle(struct device *dev)
{
return pm_generic_runtime_idle(dev);
}
static int _od_runtime_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@ -653,7 +648,7 @@ static int _od_resume_noirq(struct device *dev)
struct dev_pm_domain omap_device_pm_domain = {
.ops = {
SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
_od_runtime_idle)
NULL)
USE_PLATFORM_PM_SLEEP_OPS
.suspend_noirq = _od_suspend_noirq,
.resume_noirq = _od_resume_noirq,

View File

@ -933,7 +933,6 @@ static struct dev_pm_domain acpi_general_pm_domain = {
#ifdef CONFIG_PM_RUNTIME
.runtime_suspend = acpi_subsys_runtime_suspend,
.runtime_resume = acpi_subsys_runtime_resume,
.runtime_idle = pm_generic_runtime_idle,
#endif
#ifdef CONFIG_PM_SLEEP
.prepare = acpi_subsys_prepare,

View File

@ -284,7 +284,7 @@ static const struct dev_pm_ops amba_pm = {
SET_RUNTIME_PM_OPS(
amba_pm_runtime_suspend,
amba_pm_runtime_resume,
pm_generic_runtime_idle
NULL
)
};

View File

@ -5436,7 +5436,7 @@ static int ata_port_runtime_idle(struct device *dev)
return -EBUSY;
}
return pm_runtime_suspend(dev);
return 0;
}
static int ata_port_runtime_suspend(struct device *dev)

View File

@ -888,7 +888,6 @@ int platform_pm_restore(struct device *dev)
static const struct dev_pm_ops platform_dev_pm_ops = {
.runtime_suspend = pm_generic_runtime_suspend,
.runtime_resume = pm_generic_runtime_resume,
.runtime_idle = pm_generic_runtime_idle,
USE_PLATFORM_PM_SLEEP_OPS
};

View File

@ -2143,7 +2143,6 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
genpd->max_off_time_changed = true;
genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
genpd->domain.ops.runtime_idle = pm_generic_runtime_idle;
genpd->domain.ops.prepare = pm_genpd_prepare;
genpd->domain.ops.suspend = pm_genpd_suspend;
genpd->domain.ops.suspend_late = pm_genpd_suspend_late;

View File

@ -11,29 +11,6 @@
#include <linux/export.h>
#ifdef CONFIG_PM_RUNTIME
/**
* pm_generic_runtime_idle - Generic runtime idle callback for subsystems.
* @dev: Device to handle.
*
* If PM operations are defined for the @dev's driver and they include
* ->runtime_idle(), execute it and return its error code, if nonzero.
* Otherwise, execute pm_runtime_suspend() for the device and return 0.
*/
int pm_generic_runtime_idle(struct device *dev)
{
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
if (pm && pm->runtime_idle) {
int ret = pm->runtime_idle(dev);
if (ret)
return ret;
}
pm_runtime_suspend(dev);
return 0;
}
EXPORT_SYMBOL_GPL(pm_generic_runtime_idle);
/**
* pm_generic_runtime_suspend - Generic runtime suspend callback for subsystems.
* @dev: Device to suspend.

View File

@ -42,6 +42,7 @@
#include <linux/export.h>
#include <linux/pm_runtime.h>
#include <linux/err.h>
#include <trace/events/power.h>
#include "power.h"
@ -305,6 +306,7 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
else if (!dev->power.qos)
ret = dev_pm_qos_constraints_allocate(dev);
trace_dev_pm_qos_add_request(dev_name(dev), type, value);
if (!ret) {
req->dev = dev;
req->type = type;
@ -349,6 +351,8 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
return -EINVAL;
}
trace_dev_pm_qos_update_request(dev_name(req->dev), req->type,
new_value);
if (curr_value != new_value)
ret = apply_constraint(req, PM_QOS_UPDATE_REQ, new_value);
@ -398,6 +402,8 @@ static int __dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
if (IS_ERR_OR_NULL(req->dev->power.qos))
return -ENODEV;
trace_dev_pm_qos_remove_request(dev_name(req->dev), req->type,
PM_QOS_DEFAULT_VALUE);
ret = apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
memset(req, 0, sizeof(*req));
return ret;

View File

@ -293,11 +293,8 @@ static int rpm_idle(struct device *dev, int rpmflags)
/* Pending requests need to be canceled. */
dev->power.request = RPM_REQ_NONE;
if (dev->power.no_callbacks) {
/* Assume ->runtime_idle() callback would have suspended. */
retval = rpm_suspend(dev, rpmflags);
if (dev->power.no_callbacks)
goto out;
}
/* Carry out an asynchronous or a synchronous idle notification. */
if (rpmflags & RPM_ASYNC) {
@ -306,7 +303,8 @@ static int rpm_idle(struct device *dev, int rpmflags)
dev->power.request_pending = true;
queue_work(pm_wq, &dev->power.work);
}
goto out;
trace_rpm_return_int(dev, _THIS_IP_, 0);
return 0;
}
dev->power.idle_notification = true;
@ -326,14 +324,14 @@ static int rpm_idle(struct device *dev, int rpmflags)
callback = dev->driver->pm->runtime_idle;
if (callback)
__rpm_callback(callback, dev);
retval = __rpm_callback(callback, dev);
dev->power.idle_notification = false;
wake_up_all(&dev->power.wait_queue);
out:
trace_rpm_return_int(dev, _THIS_IP_, retval);
return retval;
return retval ? retval : rpm_suspend(dev, rpmflags);
}
/**

View File

@ -659,7 +659,7 @@ void pm_wakeup_event(struct device *dev, unsigned int msec)
}
EXPORT_SYMBOL_GPL(pm_wakeup_event);
static void print_active_wakeup_sources(void)
void pm_print_active_wakeup_sources(void)
{
struct wakeup_source *ws;
int active = 0;
@ -683,6 +683,7 @@ static void print_active_wakeup_sources(void)
last_activity_ws->name);
rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(pm_print_active_wakeup_sources);
/**
* pm_wakeup_pending - Check if power transition in progress should be aborted.
@ -707,8 +708,10 @@ bool pm_wakeup_pending(void)
}
spin_unlock_irqrestore(&events_lock, flags);
if (ret)
print_active_wakeup_sources();
if (ret) {
pr_info("PM: Wakeup pending, aborting suspend\n");
pm_print_active_wakeup_sources();
}
return ret;
}

View File

@ -1405,7 +1405,7 @@ static int dma_runtime_idle(struct device *dev)
return -EAGAIN;
}
return pm_schedule_suspend(dev, 0);
return 0;
}
/******************************************************************************

View File

@ -305,11 +305,7 @@ static const struct irq_domain_ops lnw_gpio_irq_ops = {
static int lnw_gpio_runtime_idle(struct device *dev)
{
int err = pm_schedule_suspend(dev, 500);
if (!err)
return 0;
pm_schedule_suspend(dev, 500);
return -EBUSY;
}

View File

@ -435,7 +435,7 @@ static const struct dev_pm_ops i2c_device_pm_ops = {
SET_RUNTIME_PM_OPS(
pm_generic_runtime_suspend,
pm_generic_runtime_resume,
pm_generic_runtime_idle
NULL
)
};

View File

@ -886,12 +886,6 @@ static int ab8500_gpadc_runtime_resume(struct device *dev)
return ret;
}
static int ab8500_gpadc_runtime_idle(struct device *dev)
{
pm_runtime_suspend(dev);
return 0;
}
static int ab8500_gpadc_suspend(struct device *dev)
{
struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
@ -1039,7 +1033,7 @@ static int ab8500_gpadc_remove(struct platform_device *pdev)
static const struct dev_pm_ops ab8500_gpadc_pm_ops = {
SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend,
ab8500_gpadc_runtime_resume,
ab8500_gpadc_runtime_idle)
NULL)
SET_SYSTEM_SLEEP_PM_OPS(ab8500_gpadc_suspend,
ab8500_gpadc_resume)

View File

@ -164,7 +164,7 @@ static int mmc_runtime_resume(struct device *dev)
static int mmc_runtime_idle(struct device *dev)
{
return pm_runtime_suspend(dev);
return 0;
}
#endif /* !CONFIG_PM_RUNTIME */

View File

@ -211,7 +211,7 @@ static const struct dev_pm_ops sdio_bus_pm_ops = {
SET_RUNTIME_PM_OPS(
pm_generic_runtime_suspend,
pm_generic_runtime_resume,
pm_generic_runtime_idle
NULL
)
};

View File

@ -1050,26 +1050,22 @@ static int pci_pm_runtime_idle(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int ret = 0;
/*
* If pci_dev->driver is not set (unbound), the device should
* always remain in D0 regardless of the runtime PM status
*/
if (!pci_dev->driver)
goto out;
return 0;
if (!pm)
return -ENOSYS;
if (pm->runtime_idle) {
int ret = pm->runtime_idle(dev);
if (ret)
return ret;
}
if (pm->runtime_idle)
ret = pm->runtime_idle(dev);
out:
pm_runtime_suspend(dev);
return 0;
return ret;
}
#else /* !CONFIG_PM_RUNTIME */

View File

@ -229,8 +229,6 @@ static int scsi_runtime_resume(struct device *dev)
static int scsi_runtime_idle(struct device *dev)
{
int err;
dev_dbg(dev, "scsi_runtime_idle\n");
/* Insert hooks here for targets, hosts, and transport classes */
@ -240,14 +238,11 @@ static int scsi_runtime_idle(struct device *dev)
if (sdev->request_queue->dev) {
pm_runtime_mark_last_busy(dev);
err = pm_runtime_autosuspend(dev);
} else {
err = pm_runtime_suspend(dev);
pm_runtime_autosuspend(dev);
return -EBUSY;
}
} else {
err = pm_runtime_suspend(dev);
}
return err;
return 0;
}
int scsi_autopm_get_device(struct scsi_device *sdev)

View File

@ -25,7 +25,7 @@
static int default_platform_runtime_idle(struct device *dev)
{
/* suspend synchronously to disable clocks immediately */
return pm_runtime_suspend(dev);
return 0;
}
static struct dev_pm_domain default_pm_domain = {

View File

@ -223,7 +223,7 @@ static const struct dev_pm_ops spi_pm = {
SET_RUNTIME_PM_OPS(
pm_generic_runtime_suspend,
pm_generic_runtime_resume,
pm_generic_runtime_idle
NULL
)
};

View File

@ -1248,13 +1248,8 @@ static int serial_hsu_resume(struct pci_dev *pdev)
#ifdef CONFIG_PM_RUNTIME
static int serial_hsu_runtime_idle(struct device *dev)
{
int err;
err = pm_schedule_suspend(dev, 500);
if (err)
pm_schedule_suspend(dev, 500);
return -EBUSY;
return 0;
}
static int serial_hsu_runtime_suspend(struct device *dev)

View File

@ -1765,7 +1765,8 @@ int usb_runtime_idle(struct device *dev)
*/
if (autosuspend_check(udev) == 0)
pm_runtime_autosuspend(dev);
return 0;
/* Tell the core not to suspend it, though. */
return -EBUSY;
}
int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)

View File

@ -141,7 +141,6 @@ static const struct dev_pm_ops usb_port_pm_ops = {
#ifdef CONFIG_PM_RUNTIME
.runtime_suspend = usb_port_runtime_suspend,
.runtime_resume = usb_port_runtime_resume,
.runtime_idle = pm_generic_runtime_idle,
#endif
};

View File

@ -37,7 +37,6 @@ extern void pm_runtime_enable(struct device *dev);
extern void __pm_runtime_disable(struct device *dev, bool check_resume);
extern void pm_runtime_allow(struct device *dev);
extern void pm_runtime_forbid(struct device *dev);
extern int pm_generic_runtime_idle(struct device *dev);
extern int pm_generic_runtime_suspend(struct device *dev);
extern int pm_generic_runtime_resume(struct device *dev);
extern void pm_runtime_no_callbacks(struct device *dev);
@ -143,7 +142,6 @@ static inline bool pm_runtime_active(struct device *dev) { return true; }
static inline bool pm_runtime_status_suspended(struct device *dev) { return false; }
static inline bool pm_runtime_enabled(struct device *dev) { return false; }
static inline int pm_generic_runtime_idle(struct device *dev) { return 0; }
static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; }
static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
static inline void pm_runtime_no_callbacks(struct device *dev) {}

View File

@ -363,6 +363,7 @@ extern bool pm_wakeup_pending(void);
extern bool pm_get_wakeup_count(unsigned int *count, bool block);
extern bool pm_save_wakeup_count(unsigned int count);
extern void pm_wakep_autosleep_enabled(bool set);
extern void pm_print_active_wakeup_sources(void);
static inline void lock_system_sleep(void)
{

View File

@ -5,6 +5,7 @@
#define _TRACE_POWER_H
#include <linux/ktime.h>
#include <linux/pm_qos.h>
#include <linux/tracepoint.h>
DECLARE_EVENT_CLASS(cpu,
@ -177,6 +178,178 @@ DEFINE_EVENT(power_domain, power_domain_target,
TP_ARGS(name, state, cpu_id)
);
/*
* The pm qos events are used for pm qos update
*/
DECLARE_EVENT_CLASS(pm_qos_request,
TP_PROTO(int pm_qos_class, s32 value),
TP_ARGS(pm_qos_class, value),
TP_STRUCT__entry(
__field( int, pm_qos_class )
__field( s32, value )
),
TP_fast_assign(
__entry->pm_qos_class = pm_qos_class;
__entry->value = value;
),
TP_printk("pm_qos_class=%s value=%d",
__print_symbolic(__entry->pm_qos_class,
{ PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" },
{ PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" },
{ PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }),
__entry->value)
);
DEFINE_EVENT(pm_qos_request, pm_qos_add_request,
TP_PROTO(int pm_qos_class, s32 value),
TP_ARGS(pm_qos_class, value)
);
DEFINE_EVENT(pm_qos_request, pm_qos_update_request,
TP_PROTO(int pm_qos_class, s32 value),
TP_ARGS(pm_qos_class, value)
);
DEFINE_EVENT(pm_qos_request, pm_qos_remove_request,
TP_PROTO(int pm_qos_class, s32 value),
TP_ARGS(pm_qos_class, value)
);
TRACE_EVENT(pm_qos_update_request_timeout,
TP_PROTO(int pm_qos_class, s32 value, unsigned long timeout_us),
TP_ARGS(pm_qos_class, value, timeout_us),
TP_STRUCT__entry(
__field( int, pm_qos_class )
__field( s32, value )
__field( unsigned long, timeout_us )
),
TP_fast_assign(
__entry->pm_qos_class = pm_qos_class;
__entry->value = value;
__entry->timeout_us = timeout_us;
),
TP_printk("pm_qos_class=%s value=%d, timeout_us=%ld",
__print_symbolic(__entry->pm_qos_class,
{ PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" },
{ PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" },
{ PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }),
__entry->value, __entry->timeout_us)
);
DECLARE_EVENT_CLASS(pm_qos_update,
TP_PROTO(enum pm_qos_req_action action, int prev_value, int curr_value),
TP_ARGS(action, prev_value, curr_value),
TP_STRUCT__entry(
__field( enum pm_qos_req_action, action )
__field( int, prev_value )
__field( int, curr_value )
),
TP_fast_assign(
__entry->action = action;
__entry->prev_value = prev_value;
__entry->curr_value = curr_value;
),
TP_printk("action=%s prev_value=%d curr_value=%d",
__print_symbolic(__entry->action,
{ PM_QOS_ADD_REQ, "ADD_REQ" },
{ PM_QOS_UPDATE_REQ, "UPDATE_REQ" },
{ PM_QOS_REMOVE_REQ, "REMOVE_REQ" }),
__entry->prev_value, __entry->curr_value)
);
DEFINE_EVENT(pm_qos_update, pm_qos_update_target,
TP_PROTO(enum pm_qos_req_action action, int prev_value, int curr_value),
TP_ARGS(action, prev_value, curr_value)
);
DEFINE_EVENT_PRINT(pm_qos_update, pm_qos_update_flags,
TP_PROTO(enum pm_qos_req_action action, int prev_value, int curr_value),
TP_ARGS(action, prev_value, curr_value),
TP_printk("action=%s prev_value=0x%x curr_value=0x%x",
__print_symbolic(__entry->action,
{ PM_QOS_ADD_REQ, "ADD_REQ" },
{ PM_QOS_UPDATE_REQ, "UPDATE_REQ" },
{ PM_QOS_REMOVE_REQ, "REMOVE_REQ" }),
__entry->prev_value, __entry->curr_value)
);
DECLARE_EVENT_CLASS(dev_pm_qos_request,
TP_PROTO(const char *name, enum dev_pm_qos_req_type type,
s32 new_value),
TP_ARGS(name, type, new_value),
TP_STRUCT__entry(
__string( name, name )
__field( enum dev_pm_qos_req_type, type )
__field( s32, new_value )
),
TP_fast_assign(
__assign_str(name, name);
__entry->type = type;
__entry->new_value = new_value;
),
TP_printk("device=%s type=%s new_value=%d",
__get_str(name),
__print_symbolic(__entry->type,
{ DEV_PM_QOS_LATENCY, "DEV_PM_QOS_LATENCY" },
{ DEV_PM_QOS_FLAGS, "DEV_PM_QOS_FLAGS" }),
__entry->new_value)
);
DEFINE_EVENT(dev_pm_qos_request, dev_pm_qos_add_request,
TP_PROTO(const char *name, enum dev_pm_qos_req_type type,
s32 new_value),
TP_ARGS(name, type, new_value)
);
DEFINE_EVENT(dev_pm_qos_request, dev_pm_qos_update_request,
TP_PROTO(const char *name, enum dev_pm_qos_req_type type,
s32 new_value),
TP_ARGS(name, type, new_value)
);
DEFINE_EVENT(dev_pm_qos_request, dev_pm_qos_remove_request,
TP_PROTO(const char *name, enum dev_pm_qos_req_type type,
s32 new_value),
TP_ARGS(name, type, new_value)
);
#endif /* _TRACE_POWER_H */
/* This part must be outside protection */

View File

@ -424,6 +424,8 @@ static ssize_t wakeup_count_store(struct kobject *kobj,
if (sscanf(buf, "%u", &val) == 1) {
if (pm_save_wakeup_count(val))
error = n;
else
pm_print_active_wakeup_sources();
}
out:

View File

@ -44,6 +44,7 @@
#include <linux/uaccess.h>
#include <linux/export.h>
#include <trace/events/power.h>
/*
* 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,
spin_unlock_irqrestore(&pm_qos_lock, flags);
trace_pm_qos_update_target(action, prev_value, curr_value);
if (prev_value != curr_value) {
blocking_notifier_call_chain(c->notifiers,
(unsigned long)curr_value,
@ -272,6 +274,7 @@ bool pm_qos_update_flags(struct pm_qos_flags *pqf,
spin_unlock_irqrestore(&pm_qos_lock, irqflags);
trace_pm_qos_update_flags(action, prev_value, curr_value);
return prev_value != curr_value;
}
@ -333,6 +336,7 @@ void pm_qos_add_request(struct pm_qos_request *req,
}
req->pm_qos_class = pm_qos_class;
INIT_DELAYED_WORK(&req->work, pm_qos_work_fn);
trace_pm_qos_add_request(pm_qos_class, value);
pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints,
&req->node, PM_QOS_ADD_REQ, value);
}
@ -361,6 +365,7 @@ void pm_qos_update_request(struct pm_qos_request *req,
cancel_delayed_work_sync(&req->work);
trace_pm_qos_update_request(req->pm_qos_class, new_value);
if (new_value != req->node.prio)
pm_qos_update_target(
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,
cancel_delayed_work_sync(&req->work);
trace_pm_qos_update_request_timeout(req->pm_qos_class,
new_value, timeout_us);
if (new_value != req->node.prio)
pm_qos_update_target(
pm_qos_array[req->pm_qos_class]->constraints,
@ -416,6 +423,7 @@ void pm_qos_remove_request(struct pm_qos_request *req)
cancel_delayed_work_sync(&req->work);
trace_pm_qos_remove_request(req->pm_qos_class, PM_QOS_DEFAULT_VALUE);
pm_qos_update_target(pm_qos_array[req->pm_qos_class]->constraints,
&req->node, PM_QOS_REMOVE_REQ,
PM_QOS_DEFAULT_VALUE);
@ -477,7 +485,7 @@ static int find_pm_qos_object_by_minor(int minor)
{
int pm_qos_class;
for (pm_qos_class = 0;
for (pm_qos_class = PM_QOS_CPU_DMA_LATENCY;
pm_qos_class < PM_QOS_NUM_CLASSES; pm_qos_class++) {
if (minor ==
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)
long pm_qos_class;
pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
if (pm_qos_class >= 0) {
if (pm_qos_class >= PM_QOS_CPU_DMA_LATENCY) {
struct pm_qos_request *req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
@ -584,7 +592,7 @@ static int __init pm_qos_power_init(void)
BUILD_BUG_ON(ARRAY_SIZE(pm_qos_array) != PM_QOS_NUM_CLASSES);
for (i = 1; i < PM_QOS_NUM_CLASSES; i++) {
for (i = PM_QOS_CPU_DMA_LATENCY; i < PM_QOS_NUM_CLASSES; i++) {
ret = register_pm_qos_misc(pm_qos_array[i]);
if (ret < 0) {
printk(KERN_ERR "pm_qos_param: %s setup failed\n",

View File

@ -642,8 +642,9 @@ __register_nosave_region(unsigned long start_pfn, unsigned long end_pfn,
region->end_pfn = end_pfn;
list_add_tail(&region->list, &nosave_regions);
Report:
printk(KERN_INFO "PM: Registered nosave memory: %016lx - %016lx\n",
start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT);
printk(KERN_INFO "PM: Registered nosave memory: [mem %#010llx-%#010llx]\n",
(unsigned long long) start_pfn << PAGE_SHIFT,
((unsigned long long) end_pfn << PAGE_SHIFT) - 1);
}
/*

View File

@ -269,7 +269,7 @@ int suspend_devices_and_enter(suspend_state_t state)
suspend_test_start();
error = dpm_suspend_start(PMSG_SUSPEND);
if (error) {
printk(KERN_ERR "PM: Some devices failed to suspend\n");
pr_err("PM: Some devices failed to suspend, or early wake event detected\n");
goto Recover_platform;
}
suspend_test_finish("suspend devices");