On 11/24, Viresh Kumar wrote:
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index 37fad2eb0f47..2d5c726c920f 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -235,21 +240,41 @@ 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);
Again, can't allocate with sleeping calls under RCU read lock as it may have disabled preemption.
- if (!regulators) {
rcu_read_unlock();
return 0;
- }
- uV = kmalloc_array(count, sizeof(*uV), GFP_KERNEL);
- if (!uV) {
kfree(regulators);
rcu_read_unlock();
return 0;
- }
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;
- for (i = 0; i < count; i++) {
uV[i].min = ~0;
uV[i].max = 0;
list_for_each_entry_rcu(opp, &opp_table->opp_list, node) {
if (!opp->available)
continue;
if (opp->supplies[i].u_volt_min < uV[i].min)
uV[i].min = opp->supplies[i].u_volt_min;
if (opp->supplies[i].u_volt_max > uV[i].max)
uV[i].max = opp->supplies[i].u_volt_max;
}}
rcu_read_unlock(); @@ -924,35 +960,50 @@ 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 */
s/+//
- opp = kzalloc(sizeof(*opp) + supply_size, GFP_KERNEL);
- if (!opp) {
return NULL; }kfree(table);