On 10/20, Viresh Kumar wrote:
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index 37fad2eb0f47..45c70ce07864 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -235,21 +237,44 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) return 0; }
- reg = opp_table->regulator;
- if (IS_ERR(reg)) {
- count = opp_table->regulator_count;
- if (!count) { /* Regulator may not be required for device */ rcu_read_unlock(); return 0; }
- list_for_each_entry_rcu(opp, &opp_table->opp_list, node) {
if (!opp->available)
continue;
- size = count * sizeof(*regulators);
- regulators = kmemdup(opp_table->regulators, size, GFP_KERNEL);
How do we allocate under RCU? Doesn't that spit out big warnings?
- if (!regulators) {
rcu_read_unlock();
return 0;
- }
- min_uV = kmalloc(count * (sizeof(*min_uV) + sizeof(*max_uV)),
Do we imagine min_uV is going to be a different size from max_uV? It may be better to have a struct for min/max pair and then stride them. Then the kmalloc() can become a kmalloc_array().
GFP_KERNEL);
- if (!min_uV) {
kfree(regulators);
rcu_read_unlock();
return 0;
- }
- max_uV = min_uV + count;
- for (i = 0; i < count; i++) {
min_uV[i] = ~0;
max_uV[i] = 0;
list_for_each_entry_rcu(opp, &opp_table->opp_list, node) {
if (!opp->available)
continue;
if (opp->supply.u_volt_min < min_uV)
min_uV = opp->supply.u_volt_min;
if (opp->supply.u_volt_max > max_uV)
max_uV = opp->supply.u_volt_max;
if (opp->supplies[i].u_volt_min < min_uV[i])
min_uV[i] = opp->supplies[i].u_volt_min;
if (opp->supplies[i].u_volt_max > max_uV[i])
max_uV[i] = opp->supplies[i].u_volt_max;
}}
rcu_read_unlock(); @@ -924,35 +960,49 @@ struct dev_pm_opp *_allocate_opp(struct device *dev, struct opp_table **opp_table) { struct dev_pm_opp *opp;
- int count, supply_size;
- struct opp_table *table;
- /* allocate new OPP node */
- opp = kzalloc(sizeof(*opp), GFP_KERNEL);
- if (!opp)
- table = _add_opp_table(dev);
- if (!table) return NULL;
- INIT_LIST_HEAD(&opp->node);
- /* Allocate space for at least one supply */
- count = table->regulator_count ? table->regulator_count : 1;
- supply_size = sizeof(*opp->supplies) * count;
- *opp_table = _add_opp_table(dev);
- if (!*opp_table) {
kfree(opp);
- /* allocate new OPP node + and supplies structures */
- opp = kzalloc(sizeof(*opp) + supply_size, GFP_KERNEL);
- if (!opp) {
return NULL; }kfree(table);
- opp->supplies = (struct dev_pm_opp_supply *)(opp + 1);
So put the supplies at the end of the OPP structure as an empty array?
- INIT_LIST_HEAD(&opp->node);
- *opp_table = table;
- return opp;
} static bool _opp_supported_by_regulators(struct dev_pm_opp *opp, struct opp_table *opp_table) {
- struct regulator *reg = opp_table->regulator;
- if (!IS_ERR(reg) &&
!regulator_is_supported_voltage(reg, opp->supply.u_volt_min,
opp->supply.u_volt_max)) {
pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n",
__func__, opp->supply.u_volt_min,
opp->supply.u_volt_max);
return false;
- struct regulator *reg;
- int i;
- for (i = 0; i < opp_table->regulator_count; i++) {
reg = opp_table->regulators[i];
if (!regulator_is_supported_voltage(reg,
opp->supplies[i].u_volt_min,
opp->supplies[i].u_volt_max)) {
pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n",
__func__, opp->supplies[i].u_volt_min,
opp->supplies[i].u_volt_max);
return false;
}}
return true; @@ -984,12 +1034,13 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, /* Duplicate OPPs */ dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
__func__, opp->rate, opp->supply.u_volt,
opp->available, new_opp->rate, new_opp->supply.u_volt,
new_opp->available);
__func__, opp->rate, opp->supplies[0].u_volt,
opp->available, new_opp->rate,
new_opp->supplies[0].u_volt, new_opp->available);
return opp->available &&/* Should we compare voltages for all regulators here ? */
new_opp->supply.u_volt == opp->supply.u_volt ? 0 : -EEXIST;
}new_opp->supplies[0].u_volt == opp->supplies[0].u_volt ? 0 : -EEXIST;
new_opp->opp_table = opp_table; @@ -1303,12 +1354,14 @@ void dev_pm_opp_put_prop_name(struct device *dev) EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name); /**
- dev_pm_opp_set_regulator() - Set regulator name for the device
- dev_pm_opp_set_regulators() - Set regulator names for the device
- @dev: Device for which regulator name is being set.
- @name: Name of the regulator.
- @names: Array of pointers to the names of the regulator.
- @count: Number of regulators.
- In order to support OPP switching, OPP layer needs to know the name of the
- device's regulator, as the core would be required to switch voltages as well.
- device's regulators, as the core would be required to switch voltages as
- well.
- This must be called before any OPPs are initialized for the device.
@@ -1318,11 +1371,12 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name);
- that this function is *NOT* called under RCU protection or in contexts where
- mutex cannot be locked.
*/ -int dev_pm_opp_set_regulator(struct device *dev, const char *name) +int dev_pm_opp_set_regulators(struct device *dev, const char *names[],
Make names a const char * const *? I seem to recall arrays as function arguments has some problem but my C mastery is failing right now.
unsigned int count)
{ struct opp_table *opp_table; struct regulator *reg;
- int ret;
- int ret, i;
mutex_lock(&opp_table_lock); @@ -1338,26 +1392,43 @@ int dev_pm_opp_set_regulator(struct device *dev, const char *name) goto err; }
- /* Already have a regulator set */
- if (WARN_ON(!IS_ERR(opp_table->regulator))) {
- /* Already have regulators set */
- if (WARN_ON(opp_table->regulators)) { ret = -EBUSY; goto err; }
- /* Allocate the regulator */
- reg = regulator_get_optional(dev, name);
- if (IS_ERR(reg)) {
ret = PTR_ERR(reg);
if (ret != -EPROBE_DEFER)
dev_err(dev, "%s: no regulator (%s) found: %d\n",
__func__, name, ret);
- opp_table->regulators = kmalloc_array(count,
sizeof(*opp_table->regulators),
GFP_KERNEL);
- if (!opp_table->regulators) goto err;
- for (i = 0; i < count; i++) {
reg = regulator_get_optional(dev, names[i]);
pr_info("%s: %d: %p: %s\n", __func__, __LINE__, reg, names[i]);
Debug noise?
if (IS_ERR(reg)) {
ret = PTR_ERR(reg);
if (ret != -EPROBE_DEFER)
dev_err(dev, "%s: regulator (%s) not found: %d\n",
__func__, names[i], ret);
goto free_regulators;
}
}opp_table->regulators[i] = reg;
- opp_table->regulator = reg;
- opp_table->regulator_count = count;
mutex_unlock(&opp_table_lock); return 0; +free_regulators:
- while (i != 0)
regulator_put(opp_table->regulators[--i]);
- kfree(opp_table->regulators);
- opp_table->regulators = NULL;
err: _remove_opp_table(opp_table); unlock: diff --git a/drivers/base/power/opp/debugfs.c b/drivers/base/power/opp/debugfs.c index c897676ca35f..cb5e5fde3d39 100644 --- a/drivers/base/power/opp/debugfs.c +++ b/drivers/base/power/opp/debugfs.c @@ -34,6 +34,43 @@ void opp_debug_remove_one(struct dev_pm_opp *opp) debugfs_remove_recursive(opp->dentry); } +static bool opp_debug_create_supplies(struct dev_pm_opp *opp,
struct opp_table *opp_table,
struct dentry *pdentry)
+{
- struct dentry *d;
- int i = 0;
- char name[] = "supply-X"; /* support only 0-9 supplies */
But we don't verify that's the case? Why not use kasprintf() and free() and then there isn't any limit?
- /* Always create at least supply-0 directory */
- do {
name[7] = i + '0';
/* Create per-opp directory */
d = debugfs_create_dir(name, pdentry);
if (!d)
return false;
if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d,
&opp->supplies[i].u_volt))
return false;
if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d,
&opp->supplies[i].u_volt_min))
return false;
if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d,
&opp->supplies[i].u_volt_max))
return false;
if (!debugfs_create_ulong("u_amp", S_IRUGO, d,
&opp->supplies[i].u_amp))
return false;
- } while (++i < opp_table->regulator_count);
- return true;
+}
int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table) { struct dentry *pdentry = opp_table->dentry; diff --git a/drivers/base/power/opp/of.c b/drivers/base/power/opp/of.c index b7fcd0a1b58b..c857fb07a5bc 100644 --- a/drivers/base/power/opp/of.c +++ b/drivers/base/power/opp/of.c @@ -105,12 +106,13 @@ static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table, static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev, struct opp_table *opp_table) {
- u32 microvolt[3] = {0};
- u32 val;
- int count, ret;
- u32 *microvolt, *microamp = NULL;
- int supplies, vcount, icount, ret, i, j; struct property *prop = NULL; char name[NAME_MAX];
- supplies = opp_table->regulator_count ? opp_table->regulator_count : 1;
We can't have regulator_count == 1 by default?
- /* Search for "opp-microvolt-<name>" */ if (opp_table->prop_name) { snprintf(name, sizeof(name), "opp-microvolt-%s",
@@ -155,7 +155,8 @@ enum opp_table_access {
- @supported_hw_count: Number of elements in supported_hw array.
- @prop_name: A name to postfix to many DT properties, while parsing them.
- @clk: Device's clock handle
- @regulator: Supply regulator
- @regulators: Supply regulators
- @regulator_count: Number of Power Supply regulators
Lowercase Power Supply please.
- @dentry: debugfs dentry pointer of the real device directory (not links).
- @dentry_name: Name of the real dentry.
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 5c07ae05d69a..15cb26118dc7 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -186,7 +186,10 @@ static int cpufreq_init(struct cpufreq_policy *policy) */ name = find_supply_name(cpu_dev); if (name) {
ret = dev_pm_opp_set_regulator(cpu_dev, name);
const char *names[] = {name};
ret = dev_pm_opp_set_regulators(cpu_dev, names,
We can't just do &names instead here? Hmm...
if (ret) { dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n", policy->cpu, ret);ARRAY_SIZE(names));