summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/opp/core.c52
1 files changed, 33 insertions, 19 deletions
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index d695f68fba8c..e732f97dc2f6 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -481,10 +481,15 @@ static struct dev_pm_opp *_opp_table_find_key(struct opp_table *opp_table,
unsigned long *key, int index, bool available,
unsigned long (*read)(struct dev_pm_opp *opp, int index),
bool (*compare)(struct dev_pm_opp **opp, struct dev_pm_opp *temp_opp,
- unsigned long opp_key, unsigned long key))
+ unsigned long opp_key, unsigned long key),
+ bool (*assert)(struct opp_table *opp_table))
{
struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
+ /* Assert that the requirement is met */
+ if (assert && !assert(opp_table))
+ return ERR_PTR(-EINVAL);
+
mutex_lock(&opp_table->lock);
list_for_each_entry(temp_opp, &opp_table->opp_list, node) {
@@ -509,7 +514,8 @@ static struct dev_pm_opp *
_find_key(struct device *dev, unsigned long *key, int index, bool available,
unsigned long (*read)(struct dev_pm_opp *opp, int index),
bool (*compare)(struct dev_pm_opp **opp, struct dev_pm_opp *temp_opp,
- unsigned long opp_key, unsigned long key))
+ unsigned long opp_key, unsigned long key),
+ bool (*assert)(struct opp_table *opp_table))
{
struct opp_table *opp_table;
struct dev_pm_opp *opp;
@@ -522,7 +528,7 @@ _find_key(struct device *dev, unsigned long *key, int index, bool available,
}
opp = _opp_table_find_key(opp_table, key, index, available, read,
- compare);
+ compare, assert);
dev_pm_opp_put_opp_table(opp_table);
@@ -531,35 +537,42 @@ _find_key(struct device *dev, unsigned long *key, int index, bool available,
static struct dev_pm_opp *_find_key_exact(struct device *dev,
unsigned long key, int index, bool available,
- unsigned long (*read)(struct dev_pm_opp *opp, int index))
+ unsigned long (*read)(struct dev_pm_opp *opp, int index),
+ bool (*assert)(struct opp_table *opp_table))
{
/*
* The value of key will be updated here, but will be ignored as the
* caller doesn't need it.
*/
- return _find_key(dev, &key, index, available, read, _compare_exact);
+ return _find_key(dev, &key, index, available, read, _compare_exact,
+ assert);
}
static struct dev_pm_opp *_opp_table_find_key_ceil(struct opp_table *opp_table,
unsigned long *key, int index, bool available,
- unsigned long (*read)(struct dev_pm_opp *opp, int index))
+ unsigned long (*read)(struct dev_pm_opp *opp, int index),
+ bool (*assert)(struct opp_table *opp_table))
{
return _opp_table_find_key(opp_table, key, index, available, read,
- _compare_ceil);
+ _compare_ceil, assert);
}
static struct dev_pm_opp *_find_key_ceil(struct device *dev, unsigned long *key,
int index, bool available,
- unsigned long (*read)(struct dev_pm_opp *opp, int index))
+ unsigned long (*read)(struct dev_pm_opp *opp, int index),
+ bool (*assert)(struct opp_table *opp_table))
{
- return _find_key(dev, key, index, available, read, _compare_ceil);
+ return _find_key(dev, key, index, available, read, _compare_ceil,
+ assert);
}
static struct dev_pm_opp *_find_key_floor(struct device *dev,
unsigned long *key, int index, bool available,
- unsigned long (*read)(struct dev_pm_opp *opp, int index))
+ unsigned long (*read)(struct dev_pm_opp *opp, int index),
+ bool (*assert)(struct opp_table *opp_table))
{
- return _find_key(dev, key, index, available, read, _compare_floor);
+ return _find_key(dev, key, index, available, read, _compare_floor,
+ assert);
}
/**
@@ -588,14 +601,15 @@ static struct dev_pm_opp *_find_key_floor(struct device *dev,
struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
unsigned long freq, bool available)
{
- return _find_key_exact(dev, freq, 0, available, _read_freq);
+ return _find_key_exact(dev, freq, 0, available, _read_freq, NULL);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact);
static noinline struct dev_pm_opp *_find_freq_ceil(struct opp_table *opp_table,
unsigned long *freq)
{
- return _opp_table_find_key_ceil(opp_table, freq, 0, true, _read_freq);
+ return _opp_table_find_key_ceil(opp_table, freq, 0, true, _read_freq,
+ NULL);
}
/**
@@ -619,7 +633,7 @@ static noinline struct dev_pm_opp *_find_freq_ceil(struct opp_table *opp_table,
struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
unsigned long *freq)
{
- return _find_key_ceil(dev, freq, 0, true, _read_freq);
+ return _find_key_ceil(dev, freq, 0, true, _read_freq, NULL);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil);
@@ -644,7 +658,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil);
struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
unsigned long *freq)
{
- return _find_key_floor(dev, freq, 0, true, _read_freq);
+ return _find_key_floor(dev, freq, 0, true, _read_freq, NULL);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
@@ -666,7 +680,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev,
unsigned int level)
{
- return _find_key_exact(dev, level, 0, true, _read_level);
+ return _find_key_exact(dev, level, 0, true, _read_level, NULL);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_find_level_exact);
@@ -691,7 +705,7 @@ struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev,
unsigned long temp = *level;
struct dev_pm_opp *opp;
- opp = _find_key_ceil(dev, &temp, 0, true, _read_level);
+ opp = _find_key_ceil(dev, &temp, 0, true, _read_level, NULL);
*level = temp;
return opp;
}
@@ -722,7 +736,7 @@ struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev, unsigned int *bw,
unsigned long temp = *bw;
struct dev_pm_opp *opp;
- opp = _find_key_ceil(dev, &temp, index, true, _read_bw);
+ opp = _find_key_ceil(dev, &temp, index, true, _read_bw, NULL);
*bw = temp;
return opp;
}
@@ -753,7 +767,7 @@ struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev,
unsigned long temp = *bw;
struct dev_pm_opp *opp;
- opp = _find_key_floor(dev, &temp, index, true, _read_bw);
+ opp = _find_key_floor(dev, &temp, index, true, _read_bw, NULL);
*bw = temp;
return opp;
}