lkml.org 
[lkml]   [2018]   [Nov]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 057/222] cpufreq: dt: Try freeing static OPPs only if we have added them
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Viresh Kumar <viresh.kumar@linaro.org>

    [ Upstream commit 51c99dd2c06b234575661fa1e0a1dea6c3ef566f ]

    We can not call dev_pm_opp_of_cpumask_remove_table() freely anymore
    since the latest OPP core updates as that uses reference counting to
    free resources. There are cases where no static OPPs are added (using
    DT) for a platform and trying to remove the OPP table may end up
    decrementing refcount which is already zero and hence generating
    warnings.

    Lets track if we were able to add static OPPs or not and then only
    remove the table based on that. Some reshuffling of code is also done to
    do that.

    Reported-by: Niklas Cassel <niklas.cassel@linaro.org>
    Tested-by: Niklas Cassel <niklas.cassel@linaro.org>
    Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/cpufreq/cpufreq-dt.c | 34 +++++++++++++++++++---------------
    1 file changed, 19 insertions(+), 15 deletions(-)

    --- a/drivers/cpufreq/cpufreq-dt.c
    +++ b/drivers/cpufreq/cpufreq-dt.c
    @@ -32,6 +32,7 @@ struct private_data {
    struct device *cpu_dev;
    struct thermal_cooling_device *cdev;
    const char *reg_name;
    + bool have_static_opps;
    };

    static struct freq_attr *cpufreq_dt_attr[] = {
    @@ -196,6 +197,15 @@ static int cpufreq_init(struct cpufreq_p
    }
    }

    + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    + if (!priv) {
    + ret = -ENOMEM;
    + goto out_put_regulator;
    + }
    +
    + priv->reg_name = name;
    + priv->opp_table = opp_table;
    +
    /*
    * Initialize OPP tables for all policy->cpus. They will be shared by
    * all CPUs which have marked their CPUs shared with OPP bindings.
    @@ -206,7 +216,8 @@ static int cpufreq_init(struct cpufreq_p
    *
    * OPPs might be populated at runtime, don't check for error here
    */
    - dev_pm_opp_of_cpumask_add_table(policy->cpus);
    + if (!dev_pm_opp_of_cpumask_add_table(policy->cpus))
    + priv->have_static_opps = true;

    /*
    * But we need OPP table to function so if it is not there let's
    @@ -232,19 +243,10 @@ static int cpufreq_init(struct cpufreq_p
    __func__, ret);
    }

    - priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    - if (!priv) {
    - ret = -ENOMEM;
    - goto out_free_opp;
    - }
    -
    - priv->reg_name = name;
    - priv->opp_table = opp_table;
    -
    ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
    if (ret) {
    dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
    - goto out_free_priv;
    + goto out_free_opp;
    }

    priv->cpu_dev = cpu_dev;
    @@ -280,10 +282,11 @@ static int cpufreq_init(struct cpufreq_p

    out_free_cpufreq_table:
    dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
    -out_free_priv:
    - kfree(priv);
    out_free_opp:
    - dev_pm_opp_of_cpumask_remove_table(policy->cpus);
    + if (priv->have_static_opps)
    + dev_pm_opp_of_cpumask_remove_table(policy->cpus);
    + kfree(priv);
    +out_put_regulator:
    if (name)
    dev_pm_opp_put_regulators(opp_table);
    out_put_clk:
    @@ -298,7 +301,8 @@ static int cpufreq_exit(struct cpufreq_p

    cpufreq_cooling_unregister(priv->cdev);
    dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
    - dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
    + if (priv->have_static_opps)
    + dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
    if (priv->reg_name)
    dev_pm_opp_put_regulators(priv->opp_table);


    \
     
     \ /
      Last update: 2018-11-12 00:06    [W:3.432 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site