瀏覽代碼

devfreq: rk3399_dmc: Don't use OPP structures outside of RCU locks

The OPP structures are abused to the best here, without understanding
how the OPP core and RCU locks work.

In short, the OPP pointer saved in 'rk3399_dmcfreq' can become invalid
under your nose, as the OPP core may free it.

Fix various abuses around OPP structures and calls.

Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Viresh Kumar 8 年之前
父節點
當前提交
e37d35082e
共有 1 個文件被更改,包括 5 次插入6 次删除
  1. 5 6
      drivers/devfreq/rk3399_dmc.c

+ 5 - 6
drivers/devfreq/rk3399_dmc.c

@@ -80,7 +80,6 @@ struct rk3399_dmcfreq {
 	struct regulator *vdd_center;
 	struct regulator *vdd_center;
 	unsigned long rate, target_rate;
 	unsigned long rate, target_rate;
 	unsigned long volt, target_volt;
 	unsigned long volt, target_volt;
-	struct dev_pm_opp *curr_opp;
 };
 };
 
 
 static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
 static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
@@ -102,9 +101,6 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
 	target_rate = dev_pm_opp_get_freq(opp);
 	target_rate = dev_pm_opp_get_freq(opp);
 	target_volt = dev_pm_opp_get_voltage(opp);
 	target_volt = dev_pm_opp_get_voltage(opp);
 
 
-	dmcfreq->rate = dev_pm_opp_get_freq(dmcfreq->curr_opp);
-	dmcfreq->volt = dev_pm_opp_get_voltage(dmcfreq->curr_opp);
-
 	rcu_read_unlock();
 	rcu_read_unlock();
 
 
 	if (dmcfreq->rate == target_rate)
 	if (dmcfreq->rate == target_rate)
@@ -165,7 +161,9 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
 	if (err)
 	if (err)
 		dev_err(dev, "Cannot to set vol %lu uV\n", target_volt);
 		dev_err(dev, "Cannot to set vol %lu uV\n", target_volt);
 
 
-	dmcfreq->curr_opp = opp;
+	dmcfreq->rate = target_rate;
+	dmcfreq->volt = target_volt;
+
 out:
 out:
 	mutex_unlock(&dmcfreq->lock);
 	mutex_unlock(&dmcfreq->lock);
 	return err;
 	return err;
@@ -430,8 +428,9 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev)
 		rcu_read_unlock();
 		rcu_read_unlock();
 		return PTR_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();
 	rcu_read_unlock();
-	data->curr_opp = opp;
 
 
 	rk3399_devfreq_dmc_profile.initial_freq = data->rate;
 	rk3399_devfreq_dmc_profile.initial_freq = data->rate;