mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
Merge branch 'pm-opp'
* pm-opp: (24 commits) PM / OPP: Expose _of_get_opp_desc_node as dev_pm_opp API PM / OPP: Make _find_opp_table_unlocked() static PM / OPP: Update Documentation to remove RCU specific bits PM / OPP: Simplify dev_pm_opp_get_max_volt_latency() PM / OPP: Simplify _opp_set_availability() PM / OPP: Move away from RCU locking PM / OPP: Take kref from _find_opp_table() PM / OPP: Update OPP users to put reference PM / OPP: Add 'struct kref' to struct dev_pm_opp PM / OPP: Use dev_pm_opp_get_opp_table() instead of _add_opp_table() PM / OPP: Take reference of the OPP table while adding/removing OPPs PM / OPP: Return opp_table from dev_pm_opp_set_*() routines PM / OPP: Add 'struct kref' to OPP table PM / OPP: Add per OPP table mutex PM / OPP: Split out part of _add_opp_table() and _remove_opp_table() PM / OPP: Don't expose srcu_head to register notifiers PM / OPP: Rename dev_pm_opp_get_suspend_opp() and return OPP rate PM / OPP: Don't allocate OPP table from _opp_allocate() PM / OPP: Rename and split _dev_pm_opp_remove_table() PM / OPP: Add light weight _opp_free() routine ...
This commit is contained in:
commit
64f758a07a
@ -79,22 +79,6 @@ dependent subsystems such as cpufreq are left to the discretion of the SoC
|
||||
specific framework which uses the OPP library. Similar care needs to be taken
|
||||
care to refresh the cpufreq table in cases of these operations.
|
||||
|
||||
WARNING on OPP List locking mechanism:
|
||||
-------------------------------------------------
|
||||
OPP library uses RCU for exclusivity. RCU allows the query functions to operate
|
||||
in multiple contexts and this synchronization mechanism is optimal for a read
|
||||
intensive operations on data structure as the OPP library caters to.
|
||||
|
||||
To ensure that the data retrieved are sane, the users such as SoC framework
|
||||
should ensure that the section of code operating on OPP queries are locked
|
||||
using RCU read locks. The opp_find_freq_{exact,ceil,floor},
|
||||
opp_get_{voltage, freq, opp_count} fall into this category.
|
||||
|
||||
opp_{add,enable,disable} are updaters which use mutex and implement it's own
|
||||
RCU locking mechanisms. These functions should *NOT* be called under RCU locks
|
||||
and other contexts that prevent blocking functions in RCU or mutex operations
|
||||
from working.
|
||||
|
||||
2. Initial OPP List Registration
|
||||
================================
|
||||
The SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per
|
||||
@ -137,15 +121,18 @@ functions return the matching pointer representing the opp if a match is
|
||||
found, else returns error. These errors are expected to be handled by standard
|
||||
error checks such as IS_ERR() and appropriate actions taken by the caller.
|
||||
|
||||
Callers of these functions shall call dev_pm_opp_put() after they have used the
|
||||
OPP. Otherwise the memory for the OPP will never get freed and result in
|
||||
memleak.
|
||||
|
||||
dev_pm_opp_find_freq_exact - Search for an OPP based on an *exact* frequency and
|
||||
availability. This function is especially useful to enable an OPP which
|
||||
is not available by default.
|
||||
Example: In a case when SoC framework detects a situation where a
|
||||
higher frequency could be made available, it can use this function to
|
||||
find the OPP prior to call the dev_pm_opp_enable to actually make it available.
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
/* dont operate on the pointer.. just do a sanity check.. */
|
||||
if (IS_ERR(opp)) {
|
||||
pr_err("frequency not disabled!\n");
|
||||
@ -163,9 +150,8 @@ dev_pm_opp_find_freq_floor - Search for an available OPP which is *at most* the
|
||||
frequency.
|
||||
Example: To find the highest opp for a device:
|
||||
freq = ULONG_MAX;
|
||||
rcu_read_lock();
|
||||
dev_pm_opp_find_freq_floor(dev, &freq);
|
||||
rcu_read_unlock();
|
||||
opp = dev_pm_opp_find_freq_floor(dev, &freq);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
dev_pm_opp_find_freq_ceil - Search for an available OPP which is *at least* the
|
||||
provided frequency. This function is useful while searching for a
|
||||
@ -173,17 +159,15 @@ dev_pm_opp_find_freq_ceil - Search for an available OPP which is *at least* the
|
||||
frequency.
|
||||
Example 1: To find the lowest opp for a device:
|
||||
freq = 0;
|
||||
rcu_read_lock();
|
||||
dev_pm_opp_find_freq_ceil(dev, &freq);
|
||||
rcu_read_unlock();
|
||||
opp = dev_pm_opp_find_freq_ceil(dev, &freq);
|
||||
dev_pm_opp_put(opp);
|
||||
Example 2: A simplified implementation of a SoC cpufreq_driver->target:
|
||||
soc_cpufreq_target(..)
|
||||
{
|
||||
/* Do stuff like policy checks etc. */
|
||||
/* Find the best frequency match for the req */
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_ceil(dev, &freq);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
if (!IS_ERR(opp))
|
||||
soc_switch_to_freq_voltage(freq);
|
||||
else
|
||||
@ -208,9 +192,8 @@ dev_pm_opp_enable - Make a OPP available for operation.
|
||||
implementation might choose to do something as follows:
|
||||
if (cur_temp < temp_low_thresh) {
|
||||
/* Enable 1GHz if it was disabled */
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
/* just error check */
|
||||
if (!IS_ERR(opp))
|
||||
ret = dev_pm_opp_enable(dev, 1000000000);
|
||||
@ -224,9 +207,8 @@ dev_pm_opp_disable - Make an OPP to be not available for operation
|
||||
choose to do something as follows:
|
||||
if (cur_temp > temp_high_thresh) {
|
||||
/* Disable 1GHz if it was enabled */
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
/* just error check */
|
||||
if (!IS_ERR(opp))
|
||||
ret = dev_pm_opp_disable(dev, 1000000000);
|
||||
@ -249,10 +231,9 @@ dev_pm_opp_get_voltage - Retrieve the voltage represented by the opp pointer.
|
||||
soc_switch_to_freq_voltage(freq)
|
||||
{
|
||||
/* do things */
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_ceil(dev, &freq);
|
||||
v = dev_pm_opp_get_voltage(opp);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
if (v)
|
||||
regulator_set_voltage(.., v);
|
||||
/* do other things */
|
||||
@ -266,12 +247,12 @@ dev_pm_opp_get_freq - Retrieve the freq represented by the opp pointer.
|
||||
{
|
||||
/* do things.. */
|
||||
max_freq = ULONG_MAX;
|
||||
rcu_read_lock();
|
||||
max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq);
|
||||
requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq);
|
||||
if (!IS_ERR(max_opp) && !IS_ERR(requested_opp))
|
||||
r = soc_test_validity(max_opp, requested_opp);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(max_opp);
|
||||
dev_pm_opp_put(requested_opp);
|
||||
/* do other things */
|
||||
}
|
||||
soc_test_validity(..)
|
||||
@ -289,7 +270,6 @@ dev_pm_opp_get_opp_count - Retrieve the number of available opps for a device
|
||||
soc_notify_coproc_available_frequencies()
|
||||
{
|
||||
/* Do things */
|
||||
rcu_read_lock();
|
||||
num_available = dev_pm_opp_get_opp_count(dev);
|
||||
speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL);
|
||||
/* populate the table in increasing order */
|
||||
@ -298,8 +278,8 @@ dev_pm_opp_get_opp_count - Retrieve the number of available opps for a device
|
||||
speeds[i] = freq;
|
||||
freq++;
|
||||
i++;
|
||||
dev_pm_opp_put(opp);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available);
|
||||
/* Do other things */
|
||||
|
@ -130,17 +130,16 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
|
||||
freq = clk_get_rate(clk);
|
||||
clk_put(clk);
|
||||
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_ceil(dev, &freq);
|
||||
if (IS_ERR(opp)) {
|
||||
rcu_read_unlock();
|
||||
pr_err("%s: unable to find boot up OPP for vdd_%s\n",
|
||||
__func__, vdd_name);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
bootup_volt = dev_pm_opp_get_voltage(opp);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
if (!bootup_volt) {
|
||||
pr_err("%s: unable to find voltage corresponding to the bootup OPP for vdd_%s\n",
|
||||
__func__, vdd_name);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -42,11 +42,6 @@
|
||||
*
|
||||
* WARNING: It is important for the callers to ensure refreshing their copy of
|
||||
* the table if any of the mentioned functions have been invoked in the interim.
|
||||
*
|
||||
* Locking: The internal opp_table and opp structures are RCU protected.
|
||||
* Since we just use the regular accessor functions to access the internal data
|
||||
* structures, we use RCU read lock inside this function. As a result, users of
|
||||
* this function DONOT need to use explicit locks for invoking.
|
||||
*/
|
||||
int dev_pm_opp_init_cpufreq_table(struct device *dev,
|
||||
struct cpufreq_frequency_table **table)
|
||||
@ -56,19 +51,13 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
|
||||
int i, max_opps, ret = 0;
|
||||
unsigned long rate;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
max_opps = dev_pm_opp_get_opp_count(dev);
|
||||
if (max_opps <= 0) {
|
||||
ret = max_opps ? max_opps : -ENODATA;
|
||||
goto out;
|
||||
}
|
||||
if (max_opps <= 0)
|
||||
return max_opps ? max_opps : -ENODATA;
|
||||
|
||||
freq_table = kcalloc((max_opps + 1), sizeof(*freq_table), GFP_ATOMIC);
|
||||
if (!freq_table) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!freq_table)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0, rate = 0; i < max_opps; i++, rate++) {
|
||||
/* find next rate */
|
||||
@ -83,6 +72,8 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
|
||||
/* Is Boost/turbo opp ? */
|
||||
if (dev_pm_opp_is_turbo(opp))
|
||||
freq_table[i].flags = CPUFREQ_BOOST_FREQ;
|
||||
|
||||
dev_pm_opp_put(opp);
|
||||
}
|
||||
|
||||
freq_table[i].driver_data = i;
|
||||
@ -91,7 +82,6 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
|
||||
*table = &freq_table[0];
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
if (ret)
|
||||
kfree(freq_table);
|
||||
|
||||
@ -147,12 +137,6 @@ void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of)
|
||||
* This removes the OPP tables for CPUs present in the @cpumask.
|
||||
* This should be used to remove all the OPPs entries associated with
|
||||
* the cpus in @cpumask.
|
||||
*
|
||||
* Locking: The internal opp_table and opp structures are RCU protected.
|
||||
* Hence this function internally uses RCU updater strategy with mutex locks
|
||||
* to keep the integrity of the internal data structures. Callers should ensure
|
||||
* that this function is *NOT* called under RCU protection or in contexts where
|
||||
* mutex cannot be locked.
|
||||
*/
|
||||
void dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask)
|
||||
{
|
||||
@ -169,12 +153,6 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_cpumask_remove_table);
|
||||
* @cpumask.
|
||||
*
|
||||
* Returns -ENODEV if OPP table isn't already present.
|
||||
*
|
||||
* Locking: The internal opp_table and opp structures are RCU protected.
|
||||
* Hence this function internally uses RCU updater strategy with mutex locks
|
||||
* to keep the integrity of the internal data structures. Callers should ensure
|
||||
* that this function is *NOT* called under RCU protection or in contexts where
|
||||
* mutex cannot be locked.
|
||||
*/
|
||||
int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev,
|
||||
const struct cpumask *cpumask)
|
||||
@ -184,13 +162,9 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev,
|
||||
struct device *dev;
|
||||
int cpu, ret = 0;
|
||||
|
||||
mutex_lock(&opp_table_lock);
|
||||
|
||||
opp_table = _find_opp_table(cpu_dev);
|
||||
if (IS_ERR(opp_table)) {
|
||||
ret = PTR_ERR(opp_table);
|
||||
goto unlock;
|
||||
}
|
||||
if (IS_ERR(opp_table))
|
||||
return PTR_ERR(opp_table);
|
||||
|
||||
for_each_cpu(cpu, cpumask) {
|
||||
if (cpu == cpu_dev->id)
|
||||
@ -213,8 +187,8 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev,
|
||||
/* Mark opp-table as multiple CPUs are sharing it now */
|
||||
opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED;
|
||||
}
|
||||
unlock:
|
||||
mutex_unlock(&opp_table_lock);
|
||||
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -229,12 +203,6 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus);
|
||||
*
|
||||
* Returns -ENODEV if OPP table isn't already present and -EINVAL if the OPP
|
||||
* table's status is access-unknown.
|
||||
*
|
||||
* Locking: The internal opp_table and opp structures are RCU protected.
|
||||
* Hence this function internally uses RCU updater strategy with mutex locks
|
||||
* to keep the integrity of the internal data structures. Callers should ensure
|
||||
* that this function is *NOT* called under RCU protection or in contexts where
|
||||
* mutex cannot be locked.
|
||||
*/
|
||||
int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
|
||||
{
|
||||
@ -242,17 +210,13 @@ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
|
||||
struct opp_table *opp_table;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&opp_table_lock);
|
||||
|
||||
opp_table = _find_opp_table(cpu_dev);
|
||||
if (IS_ERR(opp_table)) {
|
||||
ret = PTR_ERR(opp_table);
|
||||
goto unlock;
|
||||
}
|
||||
if (IS_ERR(opp_table))
|
||||
return PTR_ERR(opp_table);
|
||||
|
||||
if (opp_table->shared_opp == OPP_TABLE_ACCESS_UNKNOWN) {
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
goto put_opp_table;
|
||||
}
|
||||
|
||||
cpumask_clear(cpumask);
|
||||
@ -264,8 +228,8 @@ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
|
||||
cpumask_set_cpu(cpu_dev->id, cpumask);
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&opp_table_lock);
|
||||
put_opp_table:
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -24,9 +24,11 @@
|
||||
|
||||
static struct opp_table *_managed_opp(const struct device_node *np)
|
||||
{
|
||||
struct opp_table *opp_table;
|
||||
struct opp_table *opp_table, *managed_table = NULL;
|
||||
|
||||
list_for_each_entry_rcu(opp_table, &opp_tables, node) {
|
||||
mutex_lock(&opp_table_lock);
|
||||
|
||||
list_for_each_entry(opp_table, &opp_tables, node) {
|
||||
if (opp_table->np == np) {
|
||||
/*
|
||||
* Multiple devices can point to the same OPP table and
|
||||
@ -35,14 +37,18 @@ static struct opp_table *_managed_opp(const struct device_node *np)
|
||||
* But the OPPs will be considered as shared only if the
|
||||
* OPP table contains a "opp-shared" property.
|
||||
*/
|
||||
if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED)
|
||||
return opp_table;
|
||||
if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED) {
|
||||
_get_opp_table_kref(opp_table);
|
||||
managed_table = opp_table;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
mutex_unlock(&opp_table_lock);
|
||||
|
||||
return managed_table;
|
||||
}
|
||||
|
||||
void _of_init_opp_table(struct opp_table *opp_table, struct device *dev)
|
||||
@ -229,34 +235,28 @@ free_microvolt:
|
||||
* @dev: device pointer used to lookup OPP table.
|
||||
*
|
||||
* Free OPPs created using static entries present in DT.
|
||||
*
|
||||
* Locking: The internal opp_table and opp structures are RCU protected.
|
||||
* Hence this function indirectly uses RCU updater strategy with mutex locks
|
||||
* to keep the integrity of the internal data structures. Callers should ensure
|
||||
* that this function is *NOT* called under RCU protection or in contexts where
|
||||
* mutex cannot be locked.
|
||||
*/
|
||||
void dev_pm_opp_of_remove_table(struct device *dev)
|
||||
{
|
||||
_dev_pm_opp_remove_table(dev, false);
|
||||
_dev_pm_opp_find_and_remove_table(dev, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
|
||||
|
||||
/* Returns opp descriptor node for a device, caller must do of_node_put() */
|
||||
static struct device_node *_of_get_opp_desc_node(struct device *dev)
|
||||
struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* TODO: Support for multiple OPP tables.
|
||||
*
|
||||
* There should be only ONE phandle present in "operating-points-v2"
|
||||
* property.
|
||||
*/
|
||||
|
||||
return of_parse_phandle(dev->of_node, "operating-points-v2", 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_opp_desc_node);
|
||||
|
||||
/**
|
||||
* _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
|
||||
* @opp_table: OPP table
|
||||
* @dev: device for which we do this operation
|
||||
* @np: device node
|
||||
*
|
||||
@ -264,12 +264,6 @@ static struct device_node *_of_get_opp_desc_node(struct device *dev)
|
||||
* opp can be controlled using dev_pm_opp_enable/disable functions and may be
|
||||
* removed by dev_pm_opp_remove.
|
||||
*
|
||||
* Locking: The internal opp_table and opp structures are RCU protected.
|
||||
* Hence this function internally uses RCU updater strategy with mutex locks
|
||||
* to keep the integrity of the internal data structures. Callers should ensure
|
||||
* that this function is *NOT* called under RCU protection or in contexts where
|
||||
* mutex cannot be locked.
|
||||
*
|
||||
* Return:
|
||||
* 0 On success OR
|
||||
* Duplicate OPPs (both freq and volt are same) and opp->available
|
||||
@ -278,22 +272,17 @@ static struct device_node *_of_get_opp_desc_node(struct device *dev)
|
||||
* -ENOMEM Memory allocation failure
|
||||
* -EINVAL Failed parsing the OPP node
|
||||
*/
|
||||
static int _opp_add_static_v2(struct device *dev, struct device_node *np)
|
||||
static int _opp_add_static_v2(struct opp_table *opp_table, struct device *dev,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct opp_table *opp_table;
|
||||
struct dev_pm_opp *new_opp;
|
||||
u64 rate;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
/* Hold our table modification lock here */
|
||||
mutex_lock(&opp_table_lock);
|
||||
|
||||
new_opp = _allocate_opp(dev, &opp_table);
|
||||
if (!new_opp) {
|
||||
ret = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
new_opp = _opp_allocate(opp_table);
|
||||
if (!new_opp)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_property_read_u64(np, "opp-hz", &rate);
|
||||
if (ret < 0) {
|
||||
@ -327,8 +316,12 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
|
||||
goto free_opp;
|
||||
|
||||
ret = _opp_add(dev, new_opp, opp_table);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
/* Don't return error for duplicate OPPs */
|
||||
if (ret == -EBUSY)
|
||||
ret = 0;
|
||||
goto free_opp;
|
||||
}
|
||||
|
||||
/* OPP to select on device suspend */
|
||||
if (of_property_read_bool(np, "opp-suspend")) {
|
||||
@ -345,8 +338,6 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
|
||||
if (new_opp->clock_latency_ns > opp_table->clock_latency_ns_max)
|
||||
opp_table->clock_latency_ns_max = new_opp->clock_latency_ns;
|
||||
|
||||
mutex_unlock(&opp_table_lock);
|
||||
|
||||
pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n",
|
||||
__func__, new_opp->turbo, new_opp->rate,
|
||||
new_opp->supplies[0].u_volt, new_opp->supplies[0].u_volt_min,
|
||||
@ -356,13 +347,12 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
|
||||
* Notify the changes in the availability of the operable
|
||||
* frequency/voltage list.
|
||||
*/
|
||||
srcu_notifier_call_chain(&opp_table->srcu_head, OPP_EVENT_ADD, new_opp);
|
||||
blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADD, new_opp);
|
||||
return 0;
|
||||
|
||||
free_opp:
|
||||
_opp_remove(opp_table, new_opp, false);
|
||||
unlock:
|
||||
mutex_unlock(&opp_table_lock);
|
||||
_opp_free(new_opp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -373,41 +363,35 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np)
|
||||
struct opp_table *opp_table;
|
||||
int ret = 0, count = 0;
|
||||
|
||||
mutex_lock(&opp_table_lock);
|
||||
|
||||
opp_table = _managed_opp(opp_np);
|
||||
if (opp_table) {
|
||||
/* OPPs are already managed */
|
||||
if (!_add_opp_dev(dev, opp_table))
|
||||
ret = -ENOMEM;
|
||||
mutex_unlock(&opp_table_lock);
|
||||
return ret;
|
||||
goto put_opp_table;
|
||||
}
|
||||
mutex_unlock(&opp_table_lock);
|
||||
|
||||
opp_table = dev_pm_opp_get_opp_table(dev);
|
||||
if (!opp_table)
|
||||
return -ENOMEM;
|
||||
|
||||
/* We have opp-table node now, iterate over it and add OPPs */
|
||||
for_each_available_child_of_node(opp_np, np) {
|
||||
count++;
|
||||
|
||||
ret = _opp_add_static_v2(dev, np);
|
||||
ret = _opp_add_static_v2(opp_table, dev, np);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
|
||||
ret);
|
||||
goto free_table;
|
||||
_dev_pm_opp_remove_table(opp_table, dev, false);
|
||||
goto put_opp_table;
|
||||
}
|
||||
}
|
||||
|
||||
/* There should be one of more OPP defined */
|
||||
if (WARN_ON(!count))
|
||||
return -ENOENT;
|
||||
|
||||
mutex_lock(&opp_table_lock);
|
||||
|
||||
opp_table = _find_opp_table(dev);
|
||||
if (WARN_ON(IS_ERR(opp_table))) {
|
||||
ret = PTR_ERR(opp_table);
|
||||
mutex_unlock(&opp_table_lock);
|
||||
goto free_table;
|
||||
if (WARN_ON(!count)) {
|
||||
ret = -ENOENT;
|
||||
goto put_opp_table;
|
||||
}
|
||||
|
||||
opp_table->np = opp_np;
|
||||
@ -416,12 +400,8 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np)
|
||||
else
|
||||
opp_table->shared_opp = OPP_TABLE_ACCESS_EXCLUSIVE;
|
||||
|
||||
mutex_unlock(&opp_table_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
free_table:
|
||||
dev_pm_opp_of_remove_table(dev);
|
||||
put_opp_table:
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -429,9 +409,10 @@ free_table:
|
||||
/* Initializes OPP tables based on old-deprecated bindings */
|
||||
static int _of_add_opp_table_v1(struct device *dev)
|
||||
{
|
||||
struct opp_table *opp_table;
|
||||
const struct property *prop;
|
||||
const __be32 *val;
|
||||
int nr;
|
||||
int nr, ret = 0;
|
||||
|
||||
prop = of_find_property(dev->of_node, "operating-points", NULL);
|
||||
if (!prop)
|
||||
@ -449,18 +430,27 @@ static int _of_add_opp_table_v1(struct device *dev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
opp_table = dev_pm_opp_get_opp_table(dev);
|
||||
if (!opp_table)
|
||||
return -ENOMEM;
|
||||
|
||||
val = prop->value;
|
||||
while (nr) {
|
||||
unsigned long freq = be32_to_cpup(val++) * 1000;
|
||||
unsigned long volt = be32_to_cpup(val++);
|
||||
|
||||
if (_opp_add_v1(dev, freq, volt, false))
|
||||
dev_warn(dev, "%s: Failed to add OPP %ld\n",
|
||||
__func__, freq);
|
||||
ret = _opp_add_v1(opp_table, dev, freq, volt, false);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: Failed to add OPP %ld (%d)\n",
|
||||
__func__, freq, ret);
|
||||
_dev_pm_opp_remove_table(opp_table, dev, false);
|
||||
break;
|
||||
}
|
||||
nr -= 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -469,12 +459,6 @@ static int _of_add_opp_table_v1(struct device *dev)
|
||||
*
|
||||
* Register the initial OPP table with the OPP library for given device.
|
||||
*
|
||||
* Locking: The internal opp_table and opp structures are RCU protected.
|
||||
* Hence this function indirectly uses RCU updater strategy with mutex locks
|
||||
* to keep the integrity of the internal data structures. Callers should ensure
|
||||
* that this function is *NOT* called under RCU protection or in contexts where
|
||||
* mutex cannot be locked.
|
||||
*
|
||||
* Return:
|
||||
* 0 On success OR
|
||||
* Duplicate OPPs (both freq and volt are same) and opp->available
|
||||
@ -495,7 +479,7 @@ int dev_pm_opp_of_add_table(struct device *dev)
|
||||
* OPPs have two version of bindings now. The older one is deprecated,
|
||||
* try for the new binding first.
|
||||
*/
|
||||
opp_np = _of_get_opp_desc_node(dev);
|
||||
opp_np = dev_pm_opp_of_get_opp_desc_node(dev);
|
||||
if (!opp_np) {
|
||||
/*
|
||||
* Try old-deprecated bindings for backward compatibility with
|
||||
@ -519,12 +503,6 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table);
|
||||
*
|
||||
* This removes the OPP tables for CPUs present in the @cpumask.
|
||||
* This should be used only to remove static entries created from DT.
|
||||
*
|
||||
* Locking: The internal opp_table and opp structures are RCU protected.
|
||||
* Hence this function internally uses RCU updater strategy with mutex locks
|
||||
* to keep the integrity of the internal data structures. Callers should ensure
|
||||
* that this function is *NOT* called under RCU protection or in contexts where
|
||||
* mutex cannot be locked.
|
||||
*/
|
||||
void dev_pm_opp_of_cpumask_remove_table(const struct cpumask *cpumask)
|
||||
{
|
||||
@ -537,12 +515,6 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_remove_table);
|
||||
* @cpumask: cpumask for which OPP table needs to be added.
|
||||
*
|
||||
* This adds the OPP tables for CPUs present in the @cpumask.
|
||||
*
|
||||
* Locking: The internal opp_table and opp structures are RCU protected.
|
||||
* Hence this function internally uses RCU updater strategy with mutex locks
|
||||
* to keep the integrity of the internal data structures. Callers should ensure
|
||||
* that this function is *NOT* called under RCU protection or in contexts where
|
||||
* mutex cannot be locked.
|
||||
*/
|
||||
int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask)
|
||||
{
|
||||
@ -590,12 +562,6 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table);
|
||||
* This updates the @cpumask with CPUs that are sharing OPPs with @cpu_dev.
|
||||
*
|
||||
* Returns -ENOENT if operating-points-v2 isn't present for @cpu_dev.
|
||||
*
|
||||
* Locking: The internal opp_table and opp structures are RCU protected.
|
||||
* Hence this function internally uses RCU updater strategy with mutex locks
|
||||
* to keep the integrity of the internal data structures. Callers should ensure
|
||||
* that this function is *NOT* called under RCU protection or in contexts where
|
||||
* mutex cannot be locked.
|
||||
*/
|
||||
int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
|
||||
struct cpumask *cpumask)
|
||||
@ -605,7 +571,7 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
|
||||
int cpu, ret = 0;
|
||||
|
||||
/* Get OPP descriptor node */
|
||||
np = _of_get_opp_desc_node(cpu_dev);
|
||||
np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
|
||||
if (!np) {
|
||||
dev_dbg(cpu_dev, "%s: Couldn't find opp node.\n", __func__);
|
||||
return -ENOENT;
|
||||
@ -630,7 +596,7 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
|
||||
}
|
||||
|
||||
/* Get OPP descriptor node */
|
||||
tmp_np = _of_get_opp_desc_node(tcpu_dev);
|
||||
tmp_np = dev_pm_opp_of_get_opp_desc_node(tcpu_dev);
|
||||
if (!tmp_np) {
|
||||
dev_err(tcpu_dev, "%s: Couldn't find opp node.\n",
|
||||
__func__);
|
||||
|
@ -16,11 +16,11 @@
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/notifier.h>
|
||||
|
||||
struct clk;
|
||||
struct regulator;
|
||||
@ -51,11 +51,9 @@ extern struct list_head opp_tables;
|
||||
* @node: opp table node. The nodes are maintained throughout the lifetime
|
||||
* of boot. It is expected only an optimal set of OPPs are
|
||||
* added to the library by the SoC framework.
|
||||
* RCU usage: opp table is traversed with RCU locks. node
|
||||
* modification is possible realtime, hence the modifications
|
||||
* are protected by the opp_table_lock for integrity.
|
||||
* IMPORTANT: the opp nodes should be maintained in increasing
|
||||
* order.
|
||||
* @kref: for reference count of the OPP.
|
||||
* @available: true/false - marks if this OPP as available or not
|
||||
* @dynamic: not-created from static DT entries.
|
||||
* @turbo: true if turbo (boost) OPP
|
||||
@ -65,7 +63,6 @@ extern struct list_head opp_tables;
|
||||
* @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
|
||||
* frequency from any other OPP's frequency.
|
||||
* @opp_table: points back to the opp_table struct this opp belongs to
|
||||
* @rcu_head: RCU callback head used for deferred freeing
|
||||
* @np: OPP's device node.
|
||||
* @dentry: debugfs dentry pointer (per opp)
|
||||
*
|
||||
@ -73,6 +70,7 @@ extern struct list_head opp_tables;
|
||||
*/
|
||||
struct dev_pm_opp {
|
||||
struct list_head node;
|
||||
struct kref kref;
|
||||
|
||||
bool available;
|
||||
bool dynamic;
|
||||
@ -85,7 +83,6 @@ struct dev_pm_opp {
|
||||
unsigned long clock_latency_ns;
|
||||
|
||||
struct opp_table *opp_table;
|
||||
struct rcu_head rcu_head;
|
||||
|
||||
struct device_node *np;
|
||||
|
||||
@ -98,7 +95,6 @@ struct dev_pm_opp {
|
||||
* struct opp_device - devices managed by 'struct opp_table'
|
||||
* @node: list node
|
||||
* @dev: device to which the struct object belongs
|
||||
* @rcu_head: RCU callback head used for deferred freeing
|
||||
* @dentry: debugfs dentry pointer (per device)
|
||||
*
|
||||
* This is an internal data structure maintaining the devices that are managed
|
||||
@ -107,7 +103,6 @@ struct dev_pm_opp {
|
||||
struct opp_device {
|
||||
struct list_head node;
|
||||
const struct device *dev;
|
||||
struct rcu_head rcu_head;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *dentry;
|
||||
@ -125,12 +120,11 @@ enum opp_table_access {
|
||||
* @node: table node - contains the devices with OPPs that
|
||||
* have been registered. Nodes once added are not modified in this
|
||||
* table.
|
||||
* RCU usage: nodes are not modified in the table of opp_table,
|
||||
* however addition is possible and is secured by opp_table_lock
|
||||
* @srcu_head: notifier head to notify the OPP availability changes.
|
||||
* @rcu_head: RCU callback head used for deferred freeing
|
||||
* @head: notifier head to notify the OPP availability changes.
|
||||
* @dev_list: list of devices that share these OPPs
|
||||
* @opp_list: table of opps
|
||||
* @kref: for reference count of the table.
|
||||
* @lock: mutex protecting the opp_list.
|
||||
* @np: struct device_node pointer for opp's DT node.
|
||||
* @clock_latency_ns_max: Max clock latency in nanoseconds.
|
||||
* @shared_opp: OPP is shared between multiple devices.
|
||||
@ -151,18 +145,15 @@ enum opp_table_access {
|
||||
* This is an internal data structure maintaining the link to opps attached to
|
||||
* a device. This structure is not meant to be shared to users as it is
|
||||
* meant for book keeping and private to OPP library.
|
||||
*
|
||||
* Because the opp structures can be used from both rcu and srcu readers, we
|
||||
* need to wait for the grace period of both of them before freeing any
|
||||
* resources. And so we have used kfree_rcu() from within call_srcu() handlers.
|
||||
*/
|
||||
struct opp_table {
|
||||
struct list_head node;
|
||||
|
||||
struct srcu_notifier_head srcu_head;
|
||||
struct rcu_head rcu_head;
|
||||
struct blocking_notifier_head head;
|
||||
struct list_head dev_list;
|
||||
struct list_head opp_list;
|
||||
struct kref kref;
|
||||
struct mutex lock;
|
||||
|
||||
struct device_node *np;
|
||||
unsigned long clock_latency_ns_max;
|
||||
@ -190,14 +181,17 @@ struct opp_table {
|
||||
};
|
||||
|
||||
/* Routines internal to opp core */
|
||||
void _get_opp_table_kref(struct opp_table *opp_table);
|
||||
struct opp_table *_find_opp_table(struct device *dev);
|
||||
struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
|
||||
void _dev_pm_opp_remove_table(struct device *dev, bool remove_all);
|
||||
struct dev_pm_opp *_allocate_opp(struct device *dev, struct opp_table **opp_table);
|
||||
void _dev_pm_opp_remove_table(struct opp_table *opp_table, struct device *dev, bool remove_all);
|
||||
void _dev_pm_opp_find_and_remove_table(struct device *dev, bool remove_all);
|
||||
struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table);
|
||||
void _opp_free(struct dev_pm_opp *opp);
|
||||
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
|
||||
void _opp_remove(struct opp_table *opp_table, struct dev_pm_opp *opp, bool notify);
|
||||
int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt, bool dynamic);
|
||||
int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic);
|
||||
void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of);
|
||||
struct opp_table *_add_opp_table(struct device *dev);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
void _of_init_opp_table(struct opp_table *opp_table, struct device *dev);
|
||||
|
@ -633,16 +633,12 @@ static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate)
|
||||
struct dev_pm_opp *opp;
|
||||
int i, uv;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
|
||||
if (IS_ERR(opp)) {
|
||||
rcu_read_unlock();
|
||||
if (IS_ERR(opp))
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
uv = dev_pm_opp_get_voltage(opp);
|
||||
|
||||
rcu_read_unlock();
|
||||
uv = dev_pm_opp_get_voltage(opp);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
for (i = 0; i < td->i2c_lut_size; i++) {
|
||||
if (regulator_list_voltage(td->vdd_reg, td->i2c_lut[i]) == uv)
|
||||
@ -1440,8 +1436,6 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
|
||||
struct dev_pm_opp *opp;
|
||||
int lut;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
rate = ULONG_MAX;
|
||||
opp = dev_pm_opp_find_freq_floor(td->soc->dev, &rate);
|
||||
if (IS_ERR(opp)) {
|
||||
@ -1449,6 +1443,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
|
||||
goto out;
|
||||
}
|
||||
v_max = dev_pm_opp_get_voltage(opp);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
v = td->soc->cvb->min_millivolts * 1000;
|
||||
lut = find_vdd_map_entry_exact(td, v);
|
||||
@ -1465,6 +1460,8 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
|
||||
if (v_opp <= td->soc->cvb->min_millivolts * 1000)
|
||||
td->dvco_rate_min = dev_pm_opp_get_freq(opp);
|
||||
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
for (;;) {
|
||||
v += max(1, (v_max - v) / (MAX_DFLL_VOLTAGES - j));
|
||||
if (v >= v_opp)
|
||||
@ -1496,8 +1493,6 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,6 @@ static int cpufreq_init(struct cpufreq_policy *policy)
|
||||
struct private_data *priv;
|
||||
struct device *cpu_dev;
|
||||
struct clk *cpu_clk;
|
||||
struct dev_pm_opp *suspend_opp;
|
||||
unsigned int transition_latency;
|
||||
bool fallback = false;
|
||||
const char *name;
|
||||
@ -252,11 +251,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
|
||||
policy->driver_data = priv;
|
||||
policy->clk = cpu_clk;
|
||||
|
||||
rcu_read_lock();
|
||||
suspend_opp = dev_pm_opp_get_suspend_opp(cpu_dev);
|
||||
if (suspend_opp)
|
||||
policy->suspend_freq = dev_pm_opp_get_freq(suspend_opp) / 1000;
|
||||
rcu_read_unlock();
|
||||
policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000;
|
||||
|
||||
ret = cpufreq_table_validate_and_show(policy, freq_table);
|
||||
if (ret) {
|
||||
|
@ -118,12 +118,10 @@ static int init_div_table(void)
|
||||
unsigned int tmp, clk_div, ema_div, freq, volt_id;
|
||||
struct dev_pm_opp *opp;
|
||||
|
||||
rcu_read_lock();
|
||||
cpufreq_for_each_entry(pos, freq_tbl) {
|
||||
opp = dev_pm_opp_find_freq_exact(dvfs_info->dev,
|
||||
pos->frequency * 1000, true);
|
||||
if (IS_ERR(opp)) {
|
||||
rcu_read_unlock();
|
||||
dev_err(dvfs_info->dev,
|
||||
"failed to find valid OPP for %u KHZ\n",
|
||||
pos->frequency);
|
||||
@ -140,6 +138,7 @@ static int init_div_table(void)
|
||||
|
||||
/* Calculate EMA */
|
||||
volt_id = dev_pm_opp_get_voltage(opp);
|
||||
|
||||
volt_id = (MAX_VOLTAGE - volt_id) / VOLTAGE_STEP;
|
||||
if (volt_id < PMIC_HIGH_VOLT) {
|
||||
ema_div = (CPUEMA_HIGH << P0_7_CPUEMA_SHIFT) |
|
||||
@ -157,9 +156,9 @@ static int init_div_table(void)
|
||||
|
||||
__raw_writel(tmp, dvfs_info->base + XMU_PMU_P0_7 + 4 *
|
||||
(pos - freq_tbl));
|
||||
dev_pm_opp_put(opp);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -53,16 +53,15 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
|
||||
freq_hz = new_freq * 1000;
|
||||
old_freq = clk_get_rate(arm_clk) / 1000;
|
||||
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
|
||||
if (IS_ERR(opp)) {
|
||||
rcu_read_unlock();
|
||||
dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz);
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
|
||||
volt = dev_pm_opp_get_voltage(opp);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
volt_old = regulator_get_voltage(arm_reg);
|
||||
|
||||
dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
|
||||
@ -321,14 +320,15 @@ soc_opp_out:
|
||||
* freq_table initialised from OPP is therefore sorted in the
|
||||
* same order.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_exact(cpu_dev,
|
||||
freq_table[0].frequency * 1000, true);
|
||||
min_volt = dev_pm_opp_get_voltage(opp);
|
||||
dev_pm_opp_put(opp);
|
||||
opp = dev_pm_opp_find_freq_exact(cpu_dev,
|
||||
freq_table[--num].frequency * 1000, true);
|
||||
max_volt = dev_pm_opp_get_voltage(opp);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt);
|
||||
if (ret > 0)
|
||||
transition_latency += ret * 1000;
|
||||
|
@ -232,16 +232,14 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
|
||||
|
||||
freq_hz = freq_table[index].frequency * 1000;
|
||||
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
|
||||
if (IS_ERR(opp)) {
|
||||
rcu_read_unlock();
|
||||
pr_err("cpu%d: failed to find OPP for %ld\n",
|
||||
policy->cpu, freq_hz);
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
vproc = dev_pm_opp_get_voltage(opp);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
/*
|
||||
* If the new voltage or the intermediate voltage is higher than the
|
||||
@ -411,16 +409,14 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
|
||||
|
||||
/* Search a safe voltage for intermediate frequency. */
|
||||
rate = clk_get_rate(inter_clk);
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
|
||||
if (IS_ERR(opp)) {
|
||||
rcu_read_unlock();
|
||||
pr_err("failed to get intermediate opp for cpu%d\n", cpu);
|
||||
ret = PTR_ERR(opp);
|
||||
goto out_free_opp_table;
|
||||
}
|
||||
info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
info->cpu_dev = cpu_dev;
|
||||
info->proc_reg = proc_reg;
|
||||
|
@ -63,16 +63,14 @@ static int omap_target(struct cpufreq_policy *policy, unsigned int index)
|
||||
freq = ret;
|
||||
|
||||
if (mpu_reg) {
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_ceil(mpu_dev, &freq);
|
||||
if (IS_ERR(opp)) {
|
||||
rcu_read_unlock();
|
||||
dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n",
|
||||
__func__, new_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
volt = dev_pm_opp_get_voltage(opp);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
tol = volt * OPP_TOLERANCE / 100;
|
||||
volt_old = regulator_get_voltage(mpu_reg);
|
||||
}
|
||||
|
@ -160,6 +160,7 @@ static int sti_cpufreq_set_opp_info(void)
|
||||
int pcode, substrate, major, minor;
|
||||
int ret;
|
||||
char name[MAX_PCODE_NAME_LEN];
|
||||
struct opp_table *opp_table;
|
||||
|
||||
reg_fields = sti_cpufreq_match();
|
||||
if (!reg_fields) {
|
||||
@ -211,20 +212,20 @@ use_defaults:
|
||||
|
||||
snprintf(name, MAX_PCODE_NAME_LEN, "pcode%d", pcode);
|
||||
|
||||
ret = dev_pm_opp_set_prop_name(dev, name);
|
||||
if (ret) {
|
||||
opp_table = dev_pm_opp_set_prop_name(dev, name);
|
||||
if (IS_ERR(opp_table)) {
|
||||
dev_err(dev, "Failed to set prop name\n");
|
||||
return ret;
|
||||
return PTR_ERR(opp_table);
|
||||
}
|
||||
|
||||
version[0] = BIT(major);
|
||||
version[1] = BIT(minor);
|
||||
version[2] = BIT(substrate);
|
||||
|
||||
ret = dev_pm_opp_set_supported_hw(dev, version, VERSION_ELEMENTS);
|
||||
if (ret) {
|
||||
opp_table = dev_pm_opp_set_supported_hw(dev, version, VERSION_ELEMENTS);
|
||||
if (IS_ERR(opp_table)) {
|
||||
dev_err(dev, "Failed to set supported hardware\n");
|
||||
return ret;
|
||||
return PTR_ERR(opp_table);
|
||||
}
|
||||
|
||||
dev_dbg(dev, "pcode: %d major: %d minor: %d substrate: %d\n",
|
||||
|
@ -111,18 +111,16 @@ static void devfreq_set_freq_table(struct devfreq *devfreq)
|
||||
return;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
for (i = 0, freq = 0; i < profile->max_state; i++, freq++) {
|
||||
opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq);
|
||||
if (IS_ERR(opp)) {
|
||||
devm_kfree(devfreq->dev.parent, profile->freq_table);
|
||||
profile->max_state = 0;
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
dev_pm_opp_put(opp);
|
||||
profile->freq_table[i] = freq;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1112,17 +1110,16 @@ static ssize_t available_frequencies_show(struct device *d,
|
||||
ssize_t count = 0;
|
||||
unsigned long freq = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
do {
|
||||
opp = dev_pm_opp_find_freq_ceil(dev, &freq);
|
||||
if (IS_ERR(opp))
|
||||
break;
|
||||
|
||||
dev_pm_opp_put(opp);
|
||||
count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
|
||||
"%lu ", freq);
|
||||
freq++;
|
||||
} while (1);
|
||||
rcu_read_unlock();
|
||||
|
||||
/* Truncate the trailing space */
|
||||
if (count)
|
||||
@ -1224,11 +1221,8 @@ subsys_initcall(devfreq_init);
|
||||
* @freq: The frequency given to target function
|
||||
* @flags: Flags handed from devfreq framework.
|
||||
*
|
||||
* Locking: This function must be called under rcu_read_lock(). opp is a rcu
|
||||
* protected pointer. The reason for the same is that the opp pointer which is
|
||||
* returned will remain valid for use with opp_get_{voltage, freq} only while
|
||||
* under the locked area. The pointer returned must be used prior to unlocking
|
||||
* with rcu_read_unlock() to maintain the integrity of the pointer.
|
||||
* The callers are required to call dev_pm_opp_put() for the returned OPP after
|
||||
* use.
|
||||
*/
|
||||
struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
|
||||
unsigned long *freq,
|
||||
@ -1265,18 +1259,7 @@ EXPORT_SYMBOL(devfreq_recommended_opp);
|
||||
*/
|
||||
int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
|
||||
{
|
||||
struct srcu_notifier_head *nh;
|
||||
int ret = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
nh = dev_pm_opp_get_notifier(dev);
|
||||
if (IS_ERR(nh))
|
||||
ret = PTR_ERR(nh);
|
||||
rcu_read_unlock();
|
||||
if (!ret)
|
||||
ret = srcu_notifier_chain_register(nh, &devfreq->nb);
|
||||
|
||||
return ret;
|
||||
return dev_pm_opp_register_notifier(dev, &devfreq->nb);
|
||||
}
|
||||
EXPORT_SYMBOL(devfreq_register_opp_notifier);
|
||||
|
||||
@ -1292,18 +1275,7 @@ EXPORT_SYMBOL(devfreq_register_opp_notifier);
|
||||
*/
|
||||
int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)
|
||||
{
|
||||
struct srcu_notifier_head *nh;
|
||||
int ret = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
nh = dev_pm_opp_get_notifier(dev);
|
||||
if (IS_ERR(nh))
|
||||
ret = PTR_ERR(nh);
|
||||
rcu_read_unlock();
|
||||
if (!ret)
|
||||
ret = srcu_notifier_chain_unregister(nh, &devfreq->nb);
|
||||
|
||||
return ret;
|
||||
return dev_pm_opp_unregister_notifier(dev, &devfreq->nb);
|
||||
}
|
||||
EXPORT_SYMBOL(devfreq_unregister_opp_notifier);
|
||||
|
||||
|
@ -103,18 +103,17 @@ static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags)
|
||||
int ret = 0;
|
||||
|
||||
/* Get new opp-bus instance according to new bus clock */
|
||||
rcu_read_lock();
|
||||
new_opp = devfreq_recommended_opp(dev, freq, flags);
|
||||
if (IS_ERR(new_opp)) {
|
||||
dev_err(dev, "failed to get recommended opp instance\n");
|
||||
rcu_read_unlock();
|
||||
return PTR_ERR(new_opp);
|
||||
}
|
||||
|
||||
new_freq = dev_pm_opp_get_freq(new_opp);
|
||||
new_volt = dev_pm_opp_get_voltage(new_opp);
|
||||
dev_pm_opp_put(new_opp);
|
||||
|
||||
old_freq = bus->curr_freq;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (old_freq == new_freq)
|
||||
return 0;
|
||||
@ -214,17 +213,16 @@ static int exynos_bus_passive_target(struct device *dev, unsigned long *freq,
|
||||
int ret = 0;
|
||||
|
||||
/* Get new opp-bus instance according to new bus clock */
|
||||
rcu_read_lock();
|
||||
new_opp = devfreq_recommended_opp(dev, freq, flags);
|
||||
if (IS_ERR(new_opp)) {
|
||||
dev_err(dev, "failed to get recommended opp instance\n");
|
||||
rcu_read_unlock();
|
||||
return PTR_ERR(new_opp);
|
||||
}
|
||||
|
||||
new_freq = dev_pm_opp_get_freq(new_opp);
|
||||
dev_pm_opp_put(new_opp);
|
||||
|
||||
old_freq = bus->curr_freq;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (old_freq == new_freq)
|
||||
return 0;
|
||||
@ -358,16 +356,14 @@ static int exynos_bus_parse_of(struct device_node *np,
|
||||
|
||||
rate = clk_get_rate(bus->clk);
|
||||
|
||||
rcu_read_lock();
|
||||
opp = devfreq_recommended_opp(dev, &rate, 0);
|
||||
if (IS_ERR(opp)) {
|
||||
dev_err(dev, "failed to find dev_pm_opp\n");
|
||||
rcu_read_unlock();
|
||||
ret = PTR_ERR(opp);
|
||||
goto err_opp;
|
||||
}
|
||||
bus->curr_freq = dev_pm_opp_get_freq(opp);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -59,14 +59,14 @@ static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
|
||||
* list of parent device. Because in this case, *freq is temporary
|
||||
* value which is decided by ondemand governor.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
opp = devfreq_recommended_opp(parent_devfreq->dev.parent, freq, 0);
|
||||
rcu_read_unlock();
|
||||
if (IS_ERR(opp)) {
|
||||
ret = PTR_ERR(opp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
/*
|
||||
* Get the OPP table's index of decided freqeuncy by governor
|
||||
* of parent device.
|
||||
|
@ -91,17 +91,13 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
|
||||
unsigned long target_volt, target_rate;
|
||||
int err;
|
||||
|
||||
rcu_read_lock();
|
||||
opp = devfreq_recommended_opp(dev, freq, flags);
|
||||
if (IS_ERR(opp)) {
|
||||
rcu_read_unlock();
|
||||
if (IS_ERR(opp))
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
|
||||
target_rate = dev_pm_opp_get_freq(opp);
|
||||
target_volt = dev_pm_opp_get_voltage(opp);
|
||||
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
if (dmcfreq->rate == target_rate)
|
||||
return 0;
|
||||
@ -422,15 +418,13 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev)
|
||||
|
||||
data->rate = clk_get_rate(data->dmc_clk);
|
||||
|
||||
rcu_read_lock();
|
||||
opp = devfreq_recommended_opp(dev, &data->rate, 0);
|
||||
if (IS_ERR(opp)) {
|
||||
rcu_read_unlock();
|
||||
if (IS_ERR(opp))
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
|
||||
data->rate = dev_pm_opp_get_freq(opp);
|
||||
data->volt = dev_pm_opp_get_voltage(opp);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
rk3399_devfreq_dmc_profile.initial_freq = data->rate;
|
||||
|
||||
|
@ -487,15 +487,13 @@ static int tegra_devfreq_target(struct device *dev, unsigned long *freq,
|
||||
struct dev_pm_opp *opp;
|
||||
unsigned long rate = *freq * KHZ;
|
||||
|
||||
rcu_read_lock();
|
||||
opp = devfreq_recommended_opp(dev, &rate, flags);
|
||||
if (IS_ERR(opp)) {
|
||||
rcu_read_unlock();
|
||||
dev_err(dev, "Failed to find opp for %lu KHz\n", *freq);
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
rate = dev_pm_opp_get_freq(opp);
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
clk_set_min_rate(tegra->emc_clock, rate);
|
||||
clk_set_rate(tegra->emc_clock, 0);
|
||||
|
@ -297,8 +297,6 @@ static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device,
|
||||
if (!power_table)
|
||||
return -ENOMEM;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
for (freq = 0, i = 0;
|
||||
opp = dev_pm_opp_find_freq_ceil(dev, &freq), !IS_ERR(opp);
|
||||
freq++, i++) {
|
||||
@ -306,13 +304,13 @@ static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device,
|
||||
u64 power;
|
||||
|
||||
if (i >= num_opps) {
|
||||
rcu_read_unlock();
|
||||
ret = -EAGAIN;
|
||||
goto free_power_table;
|
||||
}
|
||||
|
||||
freq_mhz = freq / 1000000;
|
||||
voltage_mv = dev_pm_opp_get_voltage(opp) / 1000;
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
/*
|
||||
* Do the multiplication with MHz and millivolt so as
|
||||
@ -328,8 +326,6 @@ static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device,
|
||||
power_table[i].power = power;
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
if (i != num_opps) {
|
||||
ret = PTR_ERR(opp);
|
||||
goto free_power_table;
|
||||
@ -433,13 +429,10 @@ static int get_static_power(struct cpufreq_cooling_device *cpufreq_device,
|
||||
return 0;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
opp = dev_pm_opp_find_freq_exact(cpufreq_device->cpu_dev, freq_hz,
|
||||
true);
|
||||
voltage = dev_pm_opp_get_voltage(opp);
|
||||
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
if (voltage == 0) {
|
||||
dev_warn_ratelimited(cpufreq_device->cpu_dev,
|
||||
|
@ -113,15 +113,15 @@ static int partition_enable_opps(struct devfreq_cooling_device *dfc,
|
||||
unsigned int freq = dfc->freq_table[i];
|
||||
bool want_enable = i >= cdev_state ? true : false;
|
||||
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_exact(dev, freq, !want_enable);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (PTR_ERR(opp) == -ERANGE)
|
||||
continue;
|
||||
else if (IS_ERR(opp))
|
||||
return PTR_ERR(opp);
|
||||
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
if (want_enable)
|
||||
ret = dev_pm_opp_enable(dev, freq);
|
||||
else
|
||||
@ -221,15 +221,12 @@ get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq)
|
||||
if (!dfc->power_ops->get_static_power)
|
||||
return 0;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
opp = dev_pm_opp_find_freq_exact(dev, freq, true);
|
||||
if (IS_ERR(opp) && (PTR_ERR(opp) == -ERANGE))
|
||||
opp = dev_pm_opp_find_freq_exact(dev, freq, false);
|
||||
|
||||
voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */
|
||||
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
if (voltage == 0) {
|
||||
dev_warn_ratelimited(dev,
|
||||
@ -412,18 +409,14 @@ static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc)
|
||||
unsigned long power_dyn, voltage;
|
||||
struct dev_pm_opp *opp;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
opp = dev_pm_opp_find_freq_floor(dev, &freq);
|
||||
if (IS_ERR(opp)) {
|
||||
rcu_read_unlock();
|
||||
ret = PTR_ERR(opp);
|
||||
goto free_tables;
|
||||
}
|
||||
|
||||
voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */
|
||||
|
||||
rcu_read_unlock();
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
if (dfc->power_ops) {
|
||||
power_dyn = get_dynamic_power(dfc, freq, voltage);
|
||||
|
@ -78,6 +78,9 @@ struct dev_pm_set_opp_data {
|
||||
|
||||
#if defined(CONFIG_PM_OPP)
|
||||
|
||||
struct opp_table *dev_pm_opp_get_opp_table(struct device *dev);
|
||||
void dev_pm_opp_put_opp_table(struct opp_table *opp_table);
|
||||
|
||||
unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
|
||||
|
||||
unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
|
||||
@ -88,7 +91,7 @@ int dev_pm_opp_get_opp_count(struct device *dev);
|
||||
unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev);
|
||||
unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev);
|
||||
unsigned long dev_pm_opp_get_max_transition_latency(struct device *dev);
|
||||
struct dev_pm_opp *dev_pm_opp_get_suspend_opp(struct device *dev);
|
||||
unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev);
|
||||
|
||||
struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
|
||||
unsigned long freq,
|
||||
@ -99,6 +102,7 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
|
||||
|
||||
struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
|
||||
unsigned long *freq);
|
||||
void dev_pm_opp_put(struct dev_pm_opp *opp);
|
||||
|
||||
int dev_pm_opp_add(struct device *dev, unsigned long freq,
|
||||
unsigned long u_volt);
|
||||
@ -108,22 +112,30 @@ int dev_pm_opp_enable(struct device *dev, unsigned long freq);
|
||||
|
||||
int dev_pm_opp_disable(struct device *dev, unsigned long freq);
|
||||
|
||||
struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev);
|
||||
int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions,
|
||||
unsigned int count);
|
||||
void dev_pm_opp_put_supported_hw(struct device *dev);
|
||||
int dev_pm_opp_set_prop_name(struct device *dev, const char *name);
|
||||
void dev_pm_opp_put_prop_name(struct device *dev);
|
||||
int dev_pm_opp_register_notifier(struct device *dev, struct notifier_block *nb);
|
||||
int dev_pm_opp_unregister_notifier(struct device *dev, struct notifier_block *nb);
|
||||
|
||||
struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions, unsigned int count);
|
||||
void dev_pm_opp_put_supported_hw(struct opp_table *opp_table);
|
||||
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);
|
||||
int 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 device *dev);
|
||||
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);
|
||||
int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const struct cpumask *cpumask);
|
||||
int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask);
|
||||
void dev_pm_opp_remove_table(struct device *dev);
|
||||
void dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask);
|
||||
#else
|
||||
static inline struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_put_opp_table(struct opp_table *opp_table) {}
|
||||
|
||||
static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
|
||||
{
|
||||
return 0;
|
||||
@ -159,9 +171,9 @@ static inline unsigned long dev_pm_opp_get_max_transition_latency(struct device
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct dev_pm_opp *dev_pm_opp_get_suspend_opp(struct device *dev)
|
||||
static inline unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev)
|
||||
{
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
|
||||
@ -182,6 +194,8 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {}
|
||||
|
||||
static inline int dev_pm_opp_add(struct device *dev, unsigned long freq,
|
||||
unsigned long u_volt)
|
||||
{
|
||||
@ -202,35 +216,39 @@ static inline int dev_pm_opp_disable(struct device *dev, unsigned long freq)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct srcu_notifier_head *dev_pm_opp_get_notifier(
|
||||
struct device *dev)
|
||||
static inline int dev_pm_opp_register_notifier(struct device *dev, struct notifier_block *nb)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static inline int dev_pm_opp_unregister_notifier(struct device *dev, struct notifier_block *nb)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static inline struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev,
|
||||
const u32 *versions,
|
||||
unsigned int count)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
static inline int dev_pm_opp_set_supported_hw(struct device *dev,
|
||||
const u32 *versions,
|
||||
unsigned int count)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
static inline void dev_pm_opp_put_supported_hw(struct opp_table *opp_table) {}
|
||||
|
||||
static inline void dev_pm_opp_put_supported_hw(struct device *dev) {}
|
||||
|
||||
static inline int dev_pm_opp_register_set_opp_helper(struct device *dev,
|
||||
static inline struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev,
|
||||
int (*set_opp)(struct dev_pm_set_opp_data *data))
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_register_put_opp_helper(struct device *dev) {}
|
||||
static inline void dev_pm_opp_register_put_opp_helper(struct opp_table *opp_table) {}
|
||||
|
||||
static inline int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
|
||||
static inline struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_put_prop_name(struct device *dev) {}
|
||||
static inline void dev_pm_opp_put_prop_name(struct opp_table *opp_table) {}
|
||||
|
||||
static inline struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count)
|
||||
{
|
||||
@ -270,6 +288,7 @@ void dev_pm_opp_of_remove_table(struct device *dev);
|
||||
int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask);
|
||||
void dev_pm_opp_of_cpumask_remove_table(const struct cpumask *cpumask);
|
||||
int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask);
|
||||
struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev);
|
||||
#else
|
||||
static inline int dev_pm_opp_of_add_table(struct device *dev)
|
||||
{
|
||||
@ -293,6 +312,11 @@ static inline int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, struct
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static inline struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_OPP_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user