Merge branches 'pm-core', 'pm-opp' and 'pm-qos'
* pm-core: PM / sysfs: Constify attribute groups PM: Constify info string used in messages PM: Constify returned PM event name PM / wakeirq: Convert to SRCU * pm-opp: PM / OPP: Add dev_pm_opp_{set|put}_clkname() PM / OPP: Use - instead of @ for DT entries PM / OPP: Don't create debugfs "supply-0" directory unnecessarily PM / OPP: opp-microvolt is not optional if regulators are set PM / OPP: Don't create copy of regulators unnecessarily PM / OPP: Reorganize _generic_set_opp_regulator() * pm-qos: PM / QoS: constify *_attribute_group.
This commit is contained in:
commit
fb0356c478
|
@ -186,20 +186,20 @@ Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
|
|||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp@1000000000 {
|
||||
opp-1000000000 {
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
opp-microvolt = <975000 970000 985000>;
|
||||
opp-microamp = <70000>;
|
||||
clock-latency-ns = <300000>;
|
||||
opp-suspend;
|
||||
};
|
||||
opp@1100000000 {
|
||||
opp-1100000000 {
|
||||
opp-hz = /bits/ 64 <1100000000>;
|
||||
opp-microvolt = <1000000 980000 1010000>;
|
||||
opp-microamp = <80000>;
|
||||
clock-latency-ns = <310000>;
|
||||
};
|
||||
opp@1200000000 {
|
||||
opp-1200000000 {
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
opp-microvolt = <1025000>;
|
||||
clock-latency-ns = <290000>;
|
||||
|
@ -265,20 +265,20 @@ independently.
|
|||
* independently.
|
||||
*/
|
||||
|
||||
opp@1000000000 {
|
||||
opp-1000000000 {
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
opp-microvolt = <975000 970000 985000>;
|
||||
opp-microamp = <70000>;
|
||||
clock-latency-ns = <300000>;
|
||||
opp-suspend;
|
||||
};
|
||||
opp@1100000000 {
|
||||
opp-1100000000 {
|
||||
opp-hz = /bits/ 64 <1100000000>;
|
||||
opp-microvolt = <1000000 980000 1010000>;
|
||||
opp-microamp = <80000>;
|
||||
clock-latency-ns = <310000>;
|
||||
};
|
||||
opp@1200000000 {
|
||||
opp-1200000000 {
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
opp-microvolt = <1025000>;
|
||||
opp-microamp = <90000;
|
||||
|
@ -341,20 +341,20 @@ DVFS state together.
|
|||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp@1000000000 {
|
||||
opp-1000000000 {
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
opp-microvolt = <975000 970000 985000>;
|
||||
opp-microamp = <70000>;
|
||||
clock-latency-ns = <300000>;
|
||||
opp-suspend;
|
||||
};
|
||||
opp@1100000000 {
|
||||
opp-1100000000 {
|
||||
opp-hz = /bits/ 64 <1100000000>;
|
||||
opp-microvolt = <1000000 980000 1010000>;
|
||||
opp-microamp = <80000>;
|
||||
clock-latency-ns = <310000>;
|
||||
};
|
||||
opp@1200000000 {
|
||||
opp-1200000000 {
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
opp-microvolt = <1025000>;
|
||||
opp-microamp = <90000>;
|
||||
|
@ -367,20 +367,20 @@ DVFS state together.
|
|||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp@1300000000 {
|
||||
opp-1300000000 {
|
||||
opp-hz = /bits/ 64 <1300000000>;
|
||||
opp-microvolt = <1050000 1045000 1055000>;
|
||||
opp-microamp = <95000>;
|
||||
clock-latency-ns = <400000>;
|
||||
opp-suspend;
|
||||
};
|
||||
opp@1400000000 {
|
||||
opp-1400000000 {
|
||||
opp-hz = /bits/ 64 <1400000000>;
|
||||
opp-microvolt = <1075000>;
|
||||
opp-microamp = <100000>;
|
||||
clock-latency-ns = <400000>;
|
||||
};
|
||||
opp@1500000000 {
|
||||
opp-1500000000 {
|
||||
opp-hz = /bits/ 64 <1500000000>;
|
||||
opp-microvolt = <1100000 1010000 1110000>;
|
||||
opp-microamp = <95000>;
|
||||
|
@ -409,7 +409,7 @@ Example 4: Handling multiple regulators
|
|||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp@1000000000 {
|
||||
opp-1000000000 {
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
opp-microvolt = <970000>, /* Supply 0 */
|
||||
<960000>, /* Supply 1 */
|
||||
|
@ -422,7 +422,7 @@ Example 4: Handling multiple regulators
|
|||
|
||||
/* OR */
|
||||
|
||||
opp@1000000000 {
|
||||
opp-1000000000 {
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
opp-microvolt = <975000 970000 985000>, /* Supply 0 */
|
||||
<965000 960000 975000>, /* Supply 1 */
|
||||
|
@ -435,7 +435,7 @@ Example 4: Handling multiple regulators
|
|||
|
||||
/* OR */
|
||||
|
||||
opp@1000000000 {
|
||||
opp-1000000000 {
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
opp-microvolt = <975000 970000 985000>, /* Supply 0 */
|
||||
<965000 960000 975000>, /* Supply 1 */
|
||||
|
@ -467,7 +467,7 @@ Example 5: opp-supported-hw
|
|||
status = "okay";
|
||||
opp-shared;
|
||||
|
||||
opp@600000000 {
|
||||
opp-600000000 {
|
||||
/*
|
||||
* Supports all substrate and process versions for 0xF
|
||||
* cuts, i.e. only first four cuts.
|
||||
|
@ -478,7 +478,7 @@ Example 5: opp-supported-hw
|
|||
...
|
||||
};
|
||||
|
||||
opp@800000000 {
|
||||
opp-800000000 {
|
||||
/*
|
||||
* Supports:
|
||||
* - cuts: only one, 6th cut (represented by 6th bit).
|
||||
|
@ -510,7 +510,7 @@ Example 6: opp-microvolt-<name>, opp-microamp-<name>:
|
|||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp@1000000000 {
|
||||
opp-1000000000 {
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
opp-microvolt-slow = <915000 900000 925000>;
|
||||
opp-microvolt-fast = <975000 970000 985000>;
|
||||
|
@ -518,7 +518,7 @@ Example 6: opp-microvolt-<name>, opp-microamp-<name>:
|
|||
opp-microamp-fast = <71000>;
|
||||
};
|
||||
|
||||
opp@1200000000 {
|
||||
opp-1200000000 {
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
opp-microvolt-slow = <915000 900000 925000>, /* Supply vcc0 */
|
||||
<925000 910000 935000>; /* Supply vcc1 */
|
||||
|
|
|
@ -62,7 +62,7 @@ static pm_message_t pm_transition;
|
|||
|
||||
static int async_error;
|
||||
|
||||
static char *pm_verb(int event)
|
||||
static const char *pm_verb(int event)
|
||||
{
|
||||
switch (event) {
|
||||
case PM_EVENT_SUSPEND:
|
||||
|
@ -208,7 +208,8 @@ static ktime_t initcall_debug_start(struct device *dev)
|
|||
}
|
||||
|
||||
static void initcall_debug_report(struct device *dev, ktime_t calltime,
|
||||
int error, pm_message_t state, char *info)
|
||||
int error, pm_message_t state,
|
||||
const char *info)
|
||||
{
|
||||
ktime_t rettime;
|
||||
s64 nsecs;
|
||||
|
@ -403,21 +404,22 @@ static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t stat
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
|
||||
static void pm_dev_dbg(struct device *dev, pm_message_t state, const char *info)
|
||||
{
|
||||
dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
|
||||
((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ?
|
||||
", may wakeup" : "");
|
||||
}
|
||||
|
||||
static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
|
||||
static void pm_dev_err(struct device *dev, pm_message_t state, const char *info,
|
||||
int error)
|
||||
{
|
||||
printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
|
||||
dev_name(dev), pm_verb(state.event), info, error);
|
||||
}
|
||||
|
||||
static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
|
||||
static void dpm_show_time(ktime_t starttime, pm_message_t state,
|
||||
const char *info)
|
||||
{
|
||||
ktime_t calltime;
|
||||
u64 usecs64;
|
||||
|
@ -435,7 +437,7 @@ static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
|
|||
}
|
||||
|
||||
static int dpm_run_callback(pm_callback_t cb, struct device *dev,
|
||||
pm_message_t state, char *info)
|
||||
pm_message_t state, const char *info)
|
||||
{
|
||||
ktime_t calltime;
|
||||
int error;
|
||||
|
@ -535,7 +537,7 @@ static void dpm_watchdog_clear(struct dpm_watchdog *wd)
|
|||
static int device_resume_noirq(struct device *dev, pm_message_t state, bool async)
|
||||
{
|
||||
pm_callback_t callback = NULL;
|
||||
char *info = NULL;
|
||||
const char *info = NULL;
|
||||
int error = 0;
|
||||
|
||||
TRACE_DEVICE(dev);
|
||||
|
@ -665,7 +667,7 @@ void dpm_resume_noirq(pm_message_t state)
|
|||
static int device_resume_early(struct device *dev, pm_message_t state, bool async)
|
||||
{
|
||||
pm_callback_t callback = NULL;
|
||||
char *info = NULL;
|
||||
const char *info = NULL;
|
||||
int error = 0;
|
||||
|
||||
TRACE_DEVICE(dev);
|
||||
|
@ -793,7 +795,7 @@ EXPORT_SYMBOL_GPL(dpm_resume_start);
|
|||
static int device_resume(struct device *dev, pm_message_t state, bool async)
|
||||
{
|
||||
pm_callback_t callback = NULL;
|
||||
char *info = NULL;
|
||||
const char *info = NULL;
|
||||
int error = 0;
|
||||
DECLARE_DPM_WATCHDOG_ON_STACK(wd);
|
||||
|
||||
|
@ -955,7 +957,7 @@ void dpm_resume(pm_message_t state)
|
|||
static void device_complete(struct device *dev, pm_message_t state)
|
||||
{
|
||||
void (*callback)(struct device *) = NULL;
|
||||
char *info = NULL;
|
||||
const char *info = NULL;
|
||||
|
||||
if (dev->power.syscore)
|
||||
return;
|
||||
|
@ -1080,7 +1082,7 @@ static pm_message_t resume_event(pm_message_t sleep_state)
|
|||
static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool async)
|
||||
{
|
||||
pm_callback_t callback = NULL;
|
||||
char *info = NULL;
|
||||
const char *info = NULL;
|
||||
int error = 0;
|
||||
|
||||
TRACE_DEVICE(dev);
|
||||
|
@ -1225,7 +1227,7 @@ int dpm_suspend_noirq(pm_message_t state)
|
|||
static int __device_suspend_late(struct device *dev, pm_message_t state, bool async)
|
||||
{
|
||||
pm_callback_t callback = NULL;
|
||||
char *info = NULL;
|
||||
const char *info = NULL;
|
||||
int error = 0;
|
||||
|
||||
TRACE_DEVICE(dev);
|
||||
|
@ -1384,7 +1386,7 @@ EXPORT_SYMBOL_GPL(dpm_suspend_end);
|
|||
*/
|
||||
static int legacy_suspend(struct device *dev, pm_message_t state,
|
||||
int (*cb)(struct device *dev, pm_message_t state),
|
||||
char *info)
|
||||
const char *info)
|
||||
{
|
||||
int error;
|
||||
ktime_t calltime;
|
||||
|
@ -1426,7 +1428,7 @@ static void dpm_clear_suppliers_direct_complete(struct device *dev)
|
|||
static int __device_suspend(struct device *dev, pm_message_t state, bool async)
|
||||
{
|
||||
pm_callback_t callback = NULL;
|
||||
char *info = NULL;
|
||||
const char *info = NULL;
|
||||
int error = 0;
|
||||
DECLARE_DPM_WATCHDOG_ON_STACK(wd);
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
|
|||
{
|
||||
struct opp_table *opp_table;
|
||||
struct dev_pm_opp *opp;
|
||||
struct regulator *reg, **regulators;
|
||||
struct regulator *reg;
|
||||
unsigned long latency_ns = 0;
|
||||
int ret, i, count;
|
||||
struct {
|
||||
|
@ -198,15 +198,9 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
|
|||
if (!count)
|
||||
goto put_opp_table;
|
||||
|
||||
regulators = kmalloc_array(count, sizeof(*regulators), GFP_KERNEL);
|
||||
if (!regulators)
|
||||
goto put_opp_table;
|
||||
|
||||
uV = kmalloc_array(count, sizeof(*uV), GFP_KERNEL);
|
||||
if (!uV)
|
||||
goto free_regulators;
|
||||
|
||||
memcpy(regulators, opp_table->regulators, count * sizeof(*regulators));
|
||||
goto put_opp_table;
|
||||
|
||||
mutex_lock(&opp_table->lock);
|
||||
|
||||
|
@ -232,15 +226,13 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
|
|||
* isn't freed, while we are executing this routine.
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
reg = regulators[i];
|
||||
reg = opp_table->regulators[i];
|
||||
ret = regulator_set_voltage_time(reg, uV[i].min, uV[i].max);
|
||||
if (ret > 0)
|
||||
latency_ns += ret * 1000;
|
||||
}
|
||||
|
||||
kfree(uV);
|
||||
free_regulators:
|
||||
kfree(regulators);
|
||||
put_opp_table:
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
|
||||
|
@ -543,17 +535,18 @@ _generic_set_opp_clk_only(struct device *dev, struct clk *clk,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int _generic_set_opp(struct dev_pm_set_opp_data *data)
|
||||
static int _generic_set_opp_regulator(const struct opp_table *opp_table,
|
||||
struct device *dev,
|
||||
unsigned long old_freq,
|
||||
unsigned long freq,
|
||||
struct dev_pm_opp_supply *old_supply,
|
||||
struct dev_pm_opp_supply *new_supply)
|
||||
{
|
||||
struct dev_pm_opp_supply *old_supply = data->old_opp.supplies;
|
||||
struct dev_pm_opp_supply *new_supply = data->new_opp.supplies;
|
||||
unsigned long old_freq = data->old_opp.rate, freq = data->new_opp.rate;
|
||||
struct regulator *reg = data->regulators[0];
|
||||
struct device *dev= data->dev;
|
||||
struct regulator *reg = opp_table->regulators[0];
|
||||
int ret;
|
||||
|
||||
/* This function only supports single regulator per device */
|
||||
if (WARN_ON(data->regulator_count > 1)) {
|
||||
if (WARN_ON(opp_table->regulator_count > 1)) {
|
||||
dev_err(dev, "multiple regulators are not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -566,7 +559,7 @@ static int _generic_set_opp(struct dev_pm_set_opp_data *data)
|
|||
}
|
||||
|
||||
/* Change frequency */
|
||||
ret = _generic_set_opp_clk_only(dev, data->clk, old_freq, freq);
|
||||
ret = _generic_set_opp_clk_only(dev, opp_table->clk, old_freq, freq);
|
||||
if (ret)
|
||||
goto restore_voltage;
|
||||
|
||||
|
@ -580,12 +573,12 @@ static int _generic_set_opp(struct dev_pm_set_opp_data *data)
|
|||
return 0;
|
||||
|
||||
restore_freq:
|
||||
if (_generic_set_opp_clk_only(dev, data->clk, freq, old_freq))
|
||||
if (_generic_set_opp_clk_only(dev, opp_table->clk, freq, old_freq))
|
||||
dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
|
||||
__func__, old_freq);
|
||||
restore_voltage:
|
||||
/* This shouldn't harm even if the voltages weren't updated earlier */
|
||||
if (old_supply->u_volt)
|
||||
if (old_supply)
|
||||
_set_opp_voltage(dev, reg, old_supply);
|
||||
|
||||
return ret;
|
||||
|
@ -603,10 +596,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
|
|||
{
|
||||
struct opp_table *opp_table;
|
||||
unsigned long freq, old_freq;
|
||||
int (*set_opp)(struct dev_pm_set_opp_data *data);
|
||||
struct dev_pm_opp *old_opp, *opp;
|
||||
struct regulator **regulators;
|
||||
struct dev_pm_set_opp_data *data;
|
||||
struct clk *clk;
|
||||
int ret, size;
|
||||
|
||||
|
@ -661,38 +651,35 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
|
|||
dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n", __func__,
|
||||
old_freq, freq);
|
||||
|
||||
regulators = opp_table->regulators;
|
||||
|
||||
/* Only frequency scaling */
|
||||
if (!regulators) {
|
||||
if (!opp_table->regulators) {
|
||||
ret = _generic_set_opp_clk_only(dev, clk, old_freq, freq);
|
||||
goto put_opps;
|
||||
} else if (!opp_table->set_opp) {
|
||||
ret = _generic_set_opp_regulator(opp_table, dev, old_freq, freq,
|
||||
IS_ERR(old_opp) ? NULL : old_opp->supplies,
|
||||
opp->supplies);
|
||||
} else {
|
||||
struct dev_pm_set_opp_data *data;
|
||||
|
||||
data = opp_table->set_opp_data;
|
||||
data->regulators = opp_table->regulators;
|
||||
data->regulator_count = opp_table->regulator_count;
|
||||
data->clk = clk;
|
||||
data->dev = dev;
|
||||
|
||||
data->old_opp.rate = old_freq;
|
||||
size = sizeof(*opp->supplies) * opp_table->regulator_count;
|
||||
if (IS_ERR(old_opp))
|
||||
memset(data->old_opp.supplies, 0, size);
|
||||
else
|
||||
memcpy(data->old_opp.supplies, old_opp->supplies, size);
|
||||
|
||||
data->new_opp.rate = freq;
|
||||
memcpy(data->new_opp.supplies, opp->supplies, size);
|
||||
|
||||
ret = opp_table->set_opp(data);
|
||||
}
|
||||
|
||||
if (opp_table->set_opp)
|
||||
set_opp = opp_table->set_opp;
|
||||
else
|
||||
set_opp = _generic_set_opp;
|
||||
|
||||
data = opp_table->set_opp_data;
|
||||
data->regulators = regulators;
|
||||
data->regulator_count = opp_table->regulator_count;
|
||||
data->clk = clk;
|
||||
data->dev = dev;
|
||||
|
||||
data->old_opp.rate = old_freq;
|
||||
size = sizeof(*opp->supplies) * opp_table->regulator_count;
|
||||
if (IS_ERR(old_opp))
|
||||
memset(data->old_opp.supplies, 0, size);
|
||||
else
|
||||
memcpy(data->old_opp.supplies, old_opp->supplies, size);
|
||||
|
||||
data->new_opp.rate = freq;
|
||||
memcpy(data->new_opp.supplies, opp->supplies, size);
|
||||
|
||||
ret = set_opp(data);
|
||||
|
||||
put_opps:
|
||||
dev_pm_opp_put(opp);
|
||||
put_old_opp:
|
||||
if (!IS_ERR(old_opp))
|
||||
|
@ -1375,6 +1362,73 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulators);
|
||||
|
||||
/**
|
||||
* dev_pm_opp_set_clkname() - Set clk name for the device
|
||||
* @dev: Device for which clk name is being set.
|
||||
* @name: Clk name.
|
||||
*
|
||||
* In order to support OPP switching, OPP layer needs to get pointer to the
|
||||
* clock for the device. Simple cases work fine without using this routine (i.e.
|
||||
* by passing connection-id as NULL), but for a device with multiple clocks
|
||||
* available, the OPP core needs to know the exact name of the clk to use.
|
||||
*
|
||||
* This must be called before any OPPs are initialized for the device.
|
||||
*/
|
||||
struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char *name)
|
||||
{
|
||||
struct opp_table *opp_table;
|
||||
int ret;
|
||||
|
||||
opp_table = dev_pm_opp_get_opp_table(dev);
|
||||
if (!opp_table)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* This should be called before OPPs are initialized */
|
||||
if (WARN_ON(!list_empty(&opp_table->opp_list))) {
|
||||
ret = -EBUSY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Already have default clk set, free it */
|
||||
if (!IS_ERR(opp_table->clk))
|
||||
clk_put(opp_table->clk);
|
||||
|
||||
/* Find clk for the device */
|
||||
opp_table->clk = clk_get(dev, name);
|
||||
if (IS_ERR(opp_table->clk)) {
|
||||
ret = PTR_ERR(opp_table->clk);
|
||||
if (ret != -EPROBE_DEFER) {
|
||||
dev_err(dev, "%s: Couldn't find clock: %d\n", __func__,
|
||||
ret);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
return opp_table;
|
||||
|
||||
err:
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_opp_set_clkname);
|
||||
|
||||
/**
|
||||
* dev_pm_opp_put_clkname() - Releases resources blocked for clk.
|
||||
* @opp_table: OPP table returned from dev_pm_opp_set_clkname().
|
||||
*/
|
||||
void dev_pm_opp_put_clkname(struct opp_table *opp_table)
|
||||
{
|
||||
/* Make sure there are no concurrent readers while updating opp_table */
|
||||
WARN_ON(!list_empty(&opp_table->opp_list));
|
||||
|
||||
clk_put(opp_table->clk);
|
||||
opp_table->clk = ERR_PTR(-EINVAL);
|
||||
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_opp_put_clkname);
|
||||
|
||||
/**
|
||||
* dev_pm_opp_register_set_opp_helper() - Register custom set OPP helper
|
||||
* @dev: Device for which the helper is getting registered.
|
||||
|
|
|
@ -40,11 +40,10 @@ static bool opp_debug_create_supplies(struct dev_pm_opp *opp,
|
|||
struct dentry *pdentry)
|
||||
{
|
||||
struct dentry *d;
|
||||
int i = 0;
|
||||
int i;
|
||||
char *name;
|
||||
|
||||
/* Always create at least supply-0 directory */
|
||||
do {
|
||||
for (i = 0; i < opp_table->regulator_count; i++) {
|
||||
name = kasprintf(GFP_KERNEL, "supply-%d", i);
|
||||
|
||||
/* Create per-opp directory */
|
||||
|
@ -70,7 +69,7 @@ static bool opp_debug_create_supplies(struct dev_pm_opp *opp,
|
|||
if (!debugfs_create_ulong("u_amp", S_IRUGO, d,
|
||||
&opp->supplies[i].u_amp))
|
||||
return false;
|
||||
} while (++i < opp_table->regulator_count);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -131,8 +131,14 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
|
|||
prop = of_find_property(opp->np, name, NULL);
|
||||
|
||||
/* Missing property isn't a problem, but an invalid entry is */
|
||||
if (!prop)
|
||||
return 0;
|
||||
if (!prop) {
|
||||
if (!opp_table->regulator_count)
|
||||
return 0;
|
||||
|
||||
dev_err(dev, "%s: opp-microvolt missing although OPP managing regulators\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
vcount = of_property_count_u32_elems(opp->np, name);
|
||||
|
|
|
@ -607,7 +607,7 @@ static struct attribute *power_attrs[] = {
|
|||
#endif /* CONFIG_PM_ADVANCED_DEBUG */
|
||||
NULL,
|
||||
};
|
||||
static struct attribute_group pm_attr_group = {
|
||||
static const struct attribute_group pm_attr_group = {
|
||||
.name = power_group_name,
|
||||
.attrs = power_attrs,
|
||||
};
|
||||
|
@ -629,7 +629,7 @@ static struct attribute *wakeup_attrs[] = {
|
|||
#endif
|
||||
NULL,
|
||||
};
|
||||
static struct attribute_group pm_wakeup_attr_group = {
|
||||
static const struct attribute_group pm_wakeup_attr_group = {
|
||||
.name = power_group_name,
|
||||
.attrs = wakeup_attrs,
|
||||
};
|
||||
|
@ -644,7 +644,7 @@ static struct attribute *runtime_attrs[] = {
|
|||
&dev_attr_autosuspend_delay_ms.attr,
|
||||
NULL,
|
||||
};
|
||||
static struct attribute_group pm_runtime_attr_group = {
|
||||
static const struct attribute_group pm_runtime_attr_group = {
|
||||
.name = power_group_name,
|
||||
.attrs = runtime_attrs,
|
||||
};
|
||||
|
@ -653,7 +653,7 @@ static struct attribute *pm_qos_resume_latency_attrs[] = {
|
|||
&dev_attr_pm_qos_resume_latency_us.attr,
|
||||
NULL,
|
||||
};
|
||||
static struct attribute_group pm_qos_resume_latency_attr_group = {
|
||||
static const struct attribute_group pm_qos_resume_latency_attr_group = {
|
||||
.name = power_group_name,
|
||||
.attrs = pm_qos_resume_latency_attrs,
|
||||
};
|
||||
|
@ -662,7 +662,7 @@ static struct attribute *pm_qos_latency_tolerance_attrs[] = {
|
|||
&dev_attr_pm_qos_latency_tolerance_us.attr,
|
||||
NULL,
|
||||
};
|
||||
static struct attribute_group pm_qos_latency_tolerance_attr_group = {
|
||||
static const struct attribute_group pm_qos_latency_tolerance_attr_group = {
|
||||
.name = power_group_name,
|
||||
.attrs = pm_qos_latency_tolerance_attrs,
|
||||
};
|
||||
|
@ -672,7 +672,7 @@ static struct attribute *pm_qos_flags_attrs[] = {
|
|||
&dev_attr_pm_qos_remote_wakeup.attr,
|
||||
NULL,
|
||||
};
|
||||
static struct attribute_group pm_qos_flags_attr_group = {
|
||||
static const struct attribute_group pm_qos_flags_attr_group = {
|
||||
.name = power_group_name,
|
||||
.attrs = pm_qos_flags_attrs,
|
||||
};
|
||||
|
|
|
@ -60,6 +60,8 @@ static LIST_HEAD(wakeup_sources);
|
|||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(wakeup_count_wait_queue);
|
||||
|
||||
DEFINE_STATIC_SRCU(wakeup_srcu);
|
||||
|
||||
static struct wakeup_source deleted_ws = {
|
||||
.name = "deleted",
|
||||
.lock = __SPIN_LOCK_UNLOCKED(deleted_ws.lock),
|
||||
|
@ -198,7 +200,7 @@ void wakeup_source_remove(struct wakeup_source *ws)
|
|||
spin_lock_irqsave(&events_lock, flags);
|
||||
list_del_rcu(&ws->entry);
|
||||
spin_unlock_irqrestore(&events_lock, flags);
|
||||
synchronize_rcu();
|
||||
synchronize_srcu(&wakeup_srcu);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wakeup_source_remove);
|
||||
|
||||
|
@ -332,12 +334,12 @@ void device_wakeup_detach_irq(struct device *dev)
|
|||
void device_wakeup_arm_wake_irqs(void)
|
||||
{
|
||||
struct wakeup_source *ws;
|
||||
int srcuidx;
|
||||
|
||||
rcu_read_lock();
|
||||
srcuidx = srcu_read_lock(&wakeup_srcu);
|
||||
list_for_each_entry_rcu(ws, &wakeup_sources, entry)
|
||||
dev_pm_arm_wake_irq(ws->wakeirq);
|
||||
|
||||
rcu_read_unlock();
|
||||
srcu_read_unlock(&wakeup_srcu, srcuidx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -348,12 +350,12 @@ void device_wakeup_arm_wake_irqs(void)
|
|||
void device_wakeup_disarm_wake_irqs(void)
|
||||
{
|
||||
struct wakeup_source *ws;
|
||||
int srcuidx;
|
||||
|
||||
rcu_read_lock();
|
||||
srcuidx = srcu_read_lock(&wakeup_srcu);
|
||||
list_for_each_entry_rcu(ws, &wakeup_sources, entry)
|
||||
dev_pm_disarm_wake_irq(ws->wakeirq);
|
||||
|
||||
rcu_read_unlock();
|
||||
srcu_read_unlock(&wakeup_srcu, srcuidx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -804,10 +806,10 @@ EXPORT_SYMBOL_GPL(pm_wakeup_dev_event);
|
|||
void pm_print_active_wakeup_sources(void)
|
||||
{
|
||||
struct wakeup_source *ws;
|
||||
int active = 0;
|
||||
int srcuidx, active = 0;
|
||||
struct wakeup_source *last_activity_ws = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
srcuidx = srcu_read_lock(&wakeup_srcu);
|
||||
list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
|
||||
if (ws->active) {
|
||||
pr_debug("active wakeup source: %s\n", ws->name);
|
||||
|
@ -823,7 +825,7 @@ void pm_print_active_wakeup_sources(void)
|
|||
if (!active && last_activity_ws)
|
||||
pr_debug("last active wakeup source: %s\n",
|
||||
last_activity_ws->name);
|
||||
rcu_read_unlock();
|
||||
srcu_read_unlock(&wakeup_srcu, srcuidx);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_print_active_wakeup_sources);
|
||||
|
||||
|
@ -950,8 +952,9 @@ void pm_wakep_autosleep_enabled(bool set)
|
|||
{
|
||||
struct wakeup_source *ws;
|
||||
ktime_t now = ktime_get();
|
||||
int srcuidx;
|
||||
|
||||
rcu_read_lock();
|
||||
srcuidx = srcu_read_lock(&wakeup_srcu);
|
||||
list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
|
||||
spin_lock_irq(&ws->lock);
|
||||
if (ws->autosleep_enabled != set) {
|
||||
|
@ -965,7 +968,7 @@ void pm_wakep_autosleep_enabled(bool set)
|
|||
}
|
||||
spin_unlock_irq(&ws->lock);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
srcu_read_unlock(&wakeup_srcu, srcuidx);
|
||||
}
|
||||
#endif /* CONFIG_PM_AUTOSLEEP */
|
||||
|
||||
|
@ -1026,15 +1029,16 @@ static int print_wakeup_source_stats(struct seq_file *m,
|
|||
static int wakeup_sources_stats_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct wakeup_source *ws;
|
||||
int srcuidx;
|
||||
|
||||
seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t"
|
||||
"expire_count\tactive_since\ttotal_time\tmax_time\t"
|
||||
"last_change\tprevent_suspend_time\n");
|
||||
|
||||
rcu_read_lock();
|
||||
srcuidx = srcu_read_lock(&wakeup_srcu);
|
||||
list_for_each_entry_rcu(ws, &wakeup_sources, entry)
|
||||
print_wakeup_source_stats(m, ws);
|
||||
rcu_read_unlock();
|
||||
srcu_read_unlock(&wakeup_srcu, srcuidx);
|
||||
|
||||
print_wakeup_source_stats(m, &deleted_ws);
|
||||
|
||||
|
|
|
@ -121,6 +121,8 @@ struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name)
|
|||
void dev_pm_opp_put_prop_name(struct opp_table *opp_table);
|
||||
struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count);
|
||||
void dev_pm_opp_put_regulators(struct opp_table *opp_table);
|
||||
struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char * name);
|
||||
void dev_pm_opp_put_clkname(struct opp_table *opp_table);
|
||||
struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev, int (*set_opp)(struct dev_pm_set_opp_data *data));
|
||||
void dev_pm_opp_register_put_opp_helper(struct opp_table *opp_table);
|
||||
int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq);
|
||||
|
@ -257,6 +259,13 @@ static inline struct opp_table *dev_pm_opp_set_regulators(struct device *dev, co
|
|||
|
||||
static inline void dev_pm_opp_put_regulators(struct opp_table *opp_table) {}
|
||||
|
||||
static inline struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char * name)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_put_clkname(struct opp_table *opp_table) {}
|
||||
|
||||
static inline int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
|
|
Loading…
Reference in a new issue