forked from luck/tmp_suning_uos_patched
PM / Sleep: Make pm_op() and pm_noirq_op() return callback pointers
Make the pm_op() and pm_noirq_op() functions return pointers to appropriate callbacks instead of executing those callbacks and returning their results. This change is required for a subsequent modification that will execute the corresponding driver callback if the subsystem callback returned by either pm_op(), or pm_noirq_op() is NULL. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
This commit is contained in:
parent
b00f4dc5ff
commit
9cf519d1c1
|
@ -32,6 +32,8 @@
|
|||
#include "../base.h"
|
||||
#include "power.h"
|
||||
|
||||
typedef int (*pm_callback_t)(struct device *);
|
||||
|
||||
/*
|
||||
* The entries in the dpm_list list are in a depth first order, simply
|
||||
* because children are guaranteed to be discovered after parents, and
|
||||
|
@ -211,113 +213,70 @@ static void dpm_wait_for_children(struct device *dev, bool async)
|
|||
device_for_each_child(dev, &async, dpm_wait_fn);
|
||||
}
|
||||
|
||||
static int dpm_run_callback(struct device *dev, int (*cb)(struct device *))
|
||||
{
|
||||
ktime_t calltime;
|
||||
int error;
|
||||
|
||||
if (!cb)
|
||||
return 0;
|
||||
|
||||
calltime = initcall_debug_start(dev);
|
||||
|
||||
error = cb(dev);
|
||||
suspend_report_result(cb, error);
|
||||
|
||||
initcall_debug_report(dev, calltime, error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_op - Execute the PM operation appropriate for given PM event.
|
||||
* @dev: Device to handle.
|
||||
* pm_op - Return the PM operation appropriate for given PM event.
|
||||
* @ops: PM operations to choose from.
|
||||
* @state: PM transition of the system being carried out.
|
||||
*/
|
||||
static int pm_op(struct device *dev,
|
||||
const struct dev_pm_ops *ops,
|
||||
pm_message_t state)
|
||||
static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
switch (state.event) {
|
||||
#ifdef CONFIG_SUSPEND
|
||||
case PM_EVENT_SUSPEND:
|
||||
error = dpm_run_callback(dev, ops->suspend);
|
||||
break;
|
||||
return ops->suspend;
|
||||
case PM_EVENT_RESUME:
|
||||
error = dpm_run_callback(dev, ops->resume);
|
||||
break;
|
||||
return ops->resume;
|
||||
#endif /* CONFIG_SUSPEND */
|
||||
#ifdef CONFIG_HIBERNATE_CALLBACKS
|
||||
case PM_EVENT_FREEZE:
|
||||
case PM_EVENT_QUIESCE:
|
||||
error = dpm_run_callback(dev, ops->freeze);
|
||||
break;
|
||||
return ops->freeze;
|
||||
case PM_EVENT_HIBERNATE:
|
||||
error = dpm_run_callback(dev, ops->poweroff);
|
||||
break;
|
||||
return ops->poweroff;
|
||||
case PM_EVENT_THAW:
|
||||
case PM_EVENT_RECOVER:
|
||||
error = dpm_run_callback(dev, ops->thaw);
|
||||
return ops->thaw;
|
||||
break;
|
||||
case PM_EVENT_RESTORE:
|
||||
error = dpm_run_callback(dev, ops->restore);
|
||||
break;
|
||||
return ops->restore;
|
||||
#endif /* CONFIG_HIBERNATE_CALLBACKS */
|
||||
default:
|
||||
error = -EINVAL;
|
||||
}
|
||||
|
||||
return error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_noirq_op - Execute the PM operation appropriate for given PM event.
|
||||
* @dev: Device to handle.
|
||||
* pm_noirq_op - Return the PM operation appropriate for given PM event.
|
||||
* @ops: PM operations to choose from.
|
||||
* @state: PM transition of the system being carried out.
|
||||
*
|
||||
* The driver of @dev will not receive interrupts while this function is being
|
||||
* executed.
|
||||
*/
|
||||
static int pm_noirq_op(struct device *dev,
|
||||
const struct dev_pm_ops *ops,
|
||||
pm_message_t state)
|
||||
static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t state)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
switch (state.event) {
|
||||
#ifdef CONFIG_SUSPEND
|
||||
case PM_EVENT_SUSPEND:
|
||||
error = dpm_run_callback(dev, ops->suspend_noirq);
|
||||
break;
|
||||
return ops->suspend_noirq;
|
||||
case PM_EVENT_RESUME:
|
||||
error = dpm_run_callback(dev, ops->resume_noirq);
|
||||
break;
|
||||
return ops->resume_noirq;
|
||||
#endif /* CONFIG_SUSPEND */
|
||||
#ifdef CONFIG_HIBERNATE_CALLBACKS
|
||||
case PM_EVENT_FREEZE:
|
||||
case PM_EVENT_QUIESCE:
|
||||
error = dpm_run_callback(dev, ops->freeze_noirq);
|
||||
break;
|
||||
return ops->freeze_noirq;
|
||||
case PM_EVENT_HIBERNATE:
|
||||
error = dpm_run_callback(dev, ops->poweroff_noirq);
|
||||
break;
|
||||
return ops->poweroff_noirq;
|
||||
case PM_EVENT_THAW:
|
||||
case PM_EVENT_RECOVER:
|
||||
error = dpm_run_callback(dev, ops->thaw_noirq);
|
||||
break;
|
||||
return ops->thaw_noirq;
|
||||
case PM_EVENT_RESTORE:
|
||||
error = dpm_run_callback(dev, ops->restore_noirq);
|
||||
break;
|
||||
return ops->restore_noirq;
|
||||
#endif /* CONFIG_HIBERNATE_CALLBACKS */
|
||||
default:
|
||||
error = -EINVAL;
|
||||
}
|
||||
|
||||
return error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *pm_verb(int event)
|
||||
|
@ -375,6 +334,26 @@ static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
|
|||
usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
|
||||
}
|
||||
|
||||
static int dpm_run_callback(pm_callback_t cb, struct device *dev,
|
||||
pm_message_t state, char *info)
|
||||
{
|
||||
ktime_t calltime;
|
||||
int error;
|
||||
|
||||
if (!cb)
|
||||
return 0;
|
||||
|
||||
calltime = initcall_debug_start(dev);
|
||||
|
||||
pm_dev_dbg(dev, state, info);
|
||||
error = cb(dev);
|
||||
suspend_report_result(cb, error);
|
||||
|
||||
initcall_debug_report(dev, calltime, error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*------------------------- Resume routines -------------------------*/
|
||||
|
||||
/**
|
||||
|
@ -387,25 +366,29 @@ static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
|
|||
*/
|
||||
static int device_resume_noirq(struct device *dev, pm_message_t state)
|
||||
{
|
||||
pm_callback_t callback = NULL;
|
||||
char *info = NULL;
|
||||
int error = 0;
|
||||
|
||||
TRACE_DEVICE(dev);
|
||||
TRACE_RESUME(0);
|
||||
|
||||
if (dev->pm_domain) {
|
||||
pm_dev_dbg(dev, state, "EARLY power domain ");
|
||||
error = pm_noirq_op(dev, &dev->pm_domain->ops, state);
|
||||
info = "EARLY power domain ";
|
||||
callback = pm_noirq_op(&dev->pm_domain->ops, state);
|
||||
} else if (dev->type && dev->type->pm) {
|
||||
pm_dev_dbg(dev, state, "EARLY type ");
|
||||
error = pm_noirq_op(dev, dev->type->pm, state);
|
||||
info = "EARLY type ";
|
||||
callback = pm_noirq_op(dev->type->pm, state);
|
||||
} else if (dev->class && dev->class->pm) {
|
||||
pm_dev_dbg(dev, state, "EARLY class ");
|
||||
error = pm_noirq_op(dev, dev->class->pm, state);
|
||||
info = "EARLY class ";
|
||||
callback = pm_noirq_op(dev->class->pm, state);
|
||||
} else if (dev->bus && dev->bus->pm) {
|
||||
pm_dev_dbg(dev, state, "EARLY ");
|
||||
error = pm_noirq_op(dev, dev->bus->pm, state);
|
||||
info = "EARLY ";
|
||||
callback = pm_noirq_op(dev->bus->pm, state);
|
||||
}
|
||||
|
||||
error = dpm_run_callback(callback, dev, state, info);
|
||||
|
||||
TRACE_RESUME(error);
|
||||
return error;
|
||||
}
|
||||
|
@ -455,6 +438,8 @@ EXPORT_SYMBOL_GPL(dpm_resume_noirq);
|
|||
*/
|
||||
static int device_resume(struct device *dev, pm_message_t state, bool async)
|
||||
{
|
||||
pm_callback_t callback = NULL;
|
||||
char *info = NULL;
|
||||
int error = 0;
|
||||
bool put = false;
|
||||
|
||||
|
@ -477,40 +462,41 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
|
|||
put = true;
|
||||
|
||||
if (dev->pm_domain) {
|
||||
pm_dev_dbg(dev, state, "power domain ");
|
||||
error = pm_op(dev, &dev->pm_domain->ops, state);
|
||||
info = "power domain ";
|
||||
callback = pm_op(&dev->pm_domain->ops, state);
|
||||
goto End;
|
||||
}
|
||||
|
||||
if (dev->type && dev->type->pm) {
|
||||
pm_dev_dbg(dev, state, "type ");
|
||||
error = pm_op(dev, dev->type->pm, state);
|
||||
info = "type ";
|
||||
callback = pm_op(dev->type->pm, state);
|
||||
goto End;
|
||||
}
|
||||
|
||||
if (dev->class) {
|
||||
if (dev->class->pm) {
|
||||
pm_dev_dbg(dev, state, "class ");
|
||||
error = pm_op(dev, dev->class->pm, state);
|
||||
info = "class ";
|
||||
callback = pm_op(dev->class->pm, state);
|
||||
goto End;
|
||||
} else if (dev->class->resume) {
|
||||
pm_dev_dbg(dev, state, "legacy class ");
|
||||
error = dpm_run_callback(dev, dev->class->resume);
|
||||
info = "legacy class ";
|
||||
callback = dev->class->resume;
|
||||
goto End;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->bus) {
|
||||
if (dev->bus->pm) {
|
||||
pm_dev_dbg(dev, state, "");
|
||||
error = pm_op(dev, dev->bus->pm, state);
|
||||
info = "";
|
||||
callback = pm_op(dev->bus->pm, state);
|
||||
} else if (dev->bus->resume) {
|
||||
pm_dev_dbg(dev, state, "legacy ");
|
||||
error = dpm_run_callback(dev, dev->bus->resume);
|
||||
info = "legacy ";
|
||||
callback = dev->bus->resume;
|
||||
}
|
||||
}
|
||||
|
||||
End:
|
||||
error = dpm_run_callback(callback, dev, state, info);
|
||||
dev->power.is_suspended = false;
|
||||
|
||||
Unlock:
|
||||
|
@ -705,23 +691,24 @@ static pm_message_t resume_event(pm_message_t sleep_state)
|
|||
*/
|
||||
static int device_suspend_noirq(struct device *dev, pm_message_t state)
|
||||
{
|
||||
int error = 0;
|
||||
pm_callback_t callback = NULL;
|
||||
char *info = NULL;
|
||||
|
||||
if (dev->pm_domain) {
|
||||
pm_dev_dbg(dev, state, "LATE power domain ");
|
||||
error = pm_noirq_op(dev, &dev->pm_domain->ops, state);
|
||||
info = "LATE power domain ";
|
||||
callback = pm_noirq_op(&dev->pm_domain->ops, state);
|
||||
} else if (dev->type && dev->type->pm) {
|
||||
pm_dev_dbg(dev, state, "LATE type ");
|
||||
error = pm_noirq_op(dev, dev->type->pm, state);
|
||||
info = "LATE type ";
|
||||
callback = pm_noirq_op(dev->type->pm, state);
|
||||
} else if (dev->class && dev->class->pm) {
|
||||
pm_dev_dbg(dev, state, "LATE class ");
|
||||
error = pm_noirq_op(dev, dev->class->pm, state);
|
||||
info = "LATE class ";
|
||||
callback = pm_noirq_op(dev->class->pm, state);
|
||||
} else if (dev->bus && dev->bus->pm) {
|
||||
pm_dev_dbg(dev, state, "LATE ");
|
||||
error = pm_noirq_op(dev, dev->bus->pm, state);
|
||||
info = "LATE ";
|
||||
callback = pm_noirq_op(dev->bus->pm, state);
|
||||
}
|
||||
|
||||
return error;
|
||||
return dpm_run_callback(callback, dev, state, info);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -798,6 +785,8 @@ static int legacy_suspend(struct device *dev, pm_message_t state,
|
|||
*/
|
||||
static int __device_suspend(struct device *dev, pm_message_t state, bool async)
|
||||
{
|
||||
pm_callback_t callback = NULL;
|
||||
char *info = NULL;
|
||||
int error = 0;
|
||||
|
||||
dpm_wait_for_children(dev, async);
|
||||
|
@ -818,22 +807,22 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
|
|||
device_lock(dev);
|
||||
|
||||
if (dev->pm_domain) {
|
||||
pm_dev_dbg(dev, state, "power domain ");
|
||||
error = pm_op(dev, &dev->pm_domain->ops, state);
|
||||
goto End;
|
||||
info = "power domain ";
|
||||
callback = pm_op(&dev->pm_domain->ops, state);
|
||||
goto Run;
|
||||
}
|
||||
|
||||
if (dev->type && dev->type->pm) {
|
||||
pm_dev_dbg(dev, state, "type ");
|
||||
error = pm_op(dev, dev->type->pm, state);
|
||||
goto End;
|
||||
info = "type ";
|
||||
callback = pm_op(dev->type->pm, state);
|
||||
goto Run;
|
||||
}
|
||||
|
||||
if (dev->class) {
|
||||
if (dev->class->pm) {
|
||||
pm_dev_dbg(dev, state, "class ");
|
||||
error = pm_op(dev, dev->class->pm, state);
|
||||
goto End;
|
||||
info = "class ";
|
||||
callback = pm_op(dev->class->pm, state);
|
||||
goto Run;
|
||||
} else if (dev->class->suspend) {
|
||||
pm_dev_dbg(dev, state, "legacy class ");
|
||||
error = legacy_suspend(dev, state, dev->class->suspend);
|
||||
|
@ -843,14 +832,18 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
|
|||
|
||||
if (dev->bus) {
|
||||
if (dev->bus->pm) {
|
||||
pm_dev_dbg(dev, state, "");
|
||||
error = pm_op(dev, dev->bus->pm, state);
|
||||
info = "";
|
||||
callback = pm_op(dev->bus->pm, state);
|
||||
} else if (dev->bus->suspend) {
|
||||
pm_dev_dbg(dev, state, "legacy ");
|
||||
error = legacy_suspend(dev, state, dev->bus->suspend);
|
||||
goto End;
|
||||
}
|
||||
}
|
||||
|
||||
Run:
|
||||
error = dpm_run_callback(callback, dev, state, info);
|
||||
|
||||
End:
|
||||
if (!error) {
|
||||
dev->power.is_suspended = true;
|
||||
|
|
Loading…
Reference in New Issue
Block a user