devfreq: rk3399_dmc: Don't use OPP structures outside of RCU locks
authorViresh Kumar <viresh.kumar@linaro.org>
Mon, 5 Dec 2016 03:23:52 +0000 (08:53 +0530)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 8 Dec 2016 00:46:07 +0000 (01:46 +0100)
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>
drivers/devfreq/rk3399_dmc.c

index 971ee63584569a722e8cd91d42801f79d5b69c9e..27d2f349b53c9ae7d8cd4db31681576e0dac8354 100644 (file)
@@ -80,7 +80,6 @@ struct rk3399_dmcfreq {
        struct regulator *vdd_center;
        unsigned long rate, target_rate;
        unsigned long volt, target_volt;
-       struct dev_pm_opp *curr_opp;
 };
 
 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_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();
 
        if (dmcfreq->rate == target_rate)
@@ -165,7 +161,9 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
        if (err)
                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:
        mutex_unlock(&dmcfreq->lock);
        return err;
@@ -430,8 +428,9 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev)
                rcu_read_unlock();
                return PTR_ERR(opp);
        }
+       data->rate = dev_pm_opp_get_freq(opp);
+       data->volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
-       data->curr_opp = opp;
 
        rk3399_devfreq_dmc_profile.initial_freq = data->rate;