Merge branches 'pm-cpufreq' and 'pm-cpuidle'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 29 Dec 2014 20:23:41 +0000 (21:23 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 29 Dec 2014 20:23:41 +0000 (21:23 +0100)
* pm-cpufreq:
  cpufreq: fix a NULL pointer dereference in __cpufreq_governor()
  cpufreq-dt: defer probing if OPP table is not ready

* pm-cpuidle:
  cpuidle / ACPI: remove unused CPUIDLE_FLAG_TIME_INVALID
  cpuidle: ladder: Better idle duration measurement without using CPUIDLE_FLAG_TIME_INVALID
  cpuidle: menu: Better idle duration measurement without using CPUIDLE_FLAG_TIME_INVALID

1  2  3 
drivers/acpi/processor_idle.c
drivers/cpufreq/cpufreq-dt.c

@@@@ -334,10 -334,10 -334,10 +334,10 @@@@ static int acpi_processor_get_power_inf
   
   static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
   {
 --     acpi_status status = 0;
 ++     acpi_status status;
        u64 count;
        int current_count;
 --     int i;
 ++     int i, ret = 0;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *cst;
   
        /* There must be at least 2 elements */
        if (!cst || (cst->type != ACPI_TYPE_PACKAGE) || cst->package.count < 2) {
                printk(KERN_ERR PREFIX "not enough elements in _CST\n");
 --             status = -EFAULT;
 ++             ret = -EFAULT;
                goto end;
        }
   
        /* Validate number of power states. */
        if (count < 1 || count != cst->package.count - 1) {
                printk(KERN_ERR PREFIX "count given by _CST is not valid\n");
 --             status = -EFAULT;
 ++             ret = -EFAULT;
                goto end;
        }
   
   
        /* Validate number of power states discovered */
        if (current_count < 2)
 --             status = -EFAULT;
 ++             ret = -EFAULT;
   
         end:
        kfree(buffer.pointer);
   
 --     return status;
 ++     return ret;
   }
   
   static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
@@@@ -985,8 -985,8 -985,6 +985,6 @@@@ static int acpi_processor_setup_cpuidle
                state->flags = 0;
                switch (cx->type) {
                        case ACPI_STATE_C1:
-                       if (cx->entry_method != ACPI_CSTATE_FFH)
-                               state->flags |= CPUIDLE_FLAG_TIME_INVALID;
 -                      if (cx->entry_method == ACPI_CSTATE_FFH)
 -                              state->flags |= CPUIDLE_FLAG_TIME_VALID;
   
                        state->enter = acpi_idle_enter_c1;
                        state->enter_dead = acpi_idle_play_dead;
                        break;
   
                        case ACPI_STATE_C2:
 -                      state->flags |= CPUIDLE_FLAG_TIME_VALID;
                        state->enter = acpi_idle_enter_simple;
                        state->enter_dead = acpi_idle_play_dead;
                        drv->safe_state_index = count;
                        break;
   
                        case ACPI_STATE_C3:
 -                      state->flags |= CPUIDLE_FLAG_TIME_VALID;
                        state->enter = pr->flags.bm_check ?
                                        acpi_idle_enter_bm :
                                        acpi_idle_enter_simple;
@@@@ -1109,7 -1111,7 -1107,7 +1107,7 @@@@ static int acpi_processor_registered
   
   int acpi_processor_power_init(struct acpi_processor *pr)
   {
 --     acpi_status status = 0;
 ++     acpi_status status;
        int retval;
        struct cpuidle_device *dev;
        static int first_run;
@@@@ -58,8 -58,8 -58,6 +58,8 @@@@ static int set_target(struct cpufreq_po
        old_freq = clk_get_rate(cpu_clk) / 1000;
   
        if (!IS_ERR(cpu_reg)) {
  +             unsigned long opp_freq;
  +
                rcu_read_lock();
                opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz);
                if (IS_ERR(opp)) {
                        return PTR_ERR(opp);
                }
                volt = dev_pm_opp_get_voltage(opp);
  +             opp_freq = dev_pm_opp_get_freq(opp);
                rcu_read_unlock();
                tol = volt * priv->voltage_tolerance / 100;
                volt_old = regulator_get_voltage(cpu_reg);
  +             dev_dbg(cpu_dev, "Found OPP: %ld kHz, %ld uV\n",
  +                     opp_freq / 1000, volt);
        }
   
        dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
  -             old_freq / 1000, volt_old ? volt_old / 1000 : -1,
  +             old_freq / 1000, (volt_old > 0) ? volt_old / 1000 : -1,
                new_freq / 1000, volt ? volt / 1000 : -1);
   
        /* scaling up?  scale voltage before frequency */
        ret = clk_set_rate(cpu_clk, freq_exact);
        if (ret) {
                dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
  -             if (!IS_ERR(cpu_reg))
  +             if (!IS_ERR(cpu_reg) && volt_old > 0)
                        regulator_set_voltage_tol(cpu_reg, volt_old, tol);
                return ret;
        }
@@@@ -186,6 -186,6 -181,7 +186,6 @@@@ static int cpufreq_init(struct cpufreq_
   {
        struct cpufreq_dt_platform_data *pd;
        struct cpufreq_frequency_table *freq_table;
  -     struct thermal_cooling_device *cdev;
        struct device_node *np;
        struct private_data *priv;
        struct device *cpu_dev;
   
        ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk);
        if (ret) {
 --             pr_err("%s: Failed to allocate resources\n: %d", __func__, ret);
 ++             pr_err("%s: Failed to allocate resources: %d\n", __func__, ret);
                return ret;
        }
   
        /* OPPs might be populated at runtime, don't check for error here */
        of_init_opp_table(cpu_dev);
   
+ +     /*
+ +      * But we need OPP table to function so if it is not there let's
+ +      * give platform code chance to provide it for us.
+ +      */
+ +     ret = dev_pm_opp_get_opp_count(cpu_dev);
+ +     if (ret <= 0) {
+ +             pr_debug("OPP table is not ready, deferring probe\n");
+ +             ret = -EPROBE_DEFER;
+ +             goto out_free_opp;
+ +     }
+ +
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv) {
                ret = -ENOMEM;
  -             goto out_put_node;
  +             goto out_free_opp;
        }
   
        of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance);
                goto out_free_priv;
        }
   
  -     /*
  -      * For now, just loading the cooling device;
  -      * thermal DT code takes care of matching them.
  -      */
  -     if (of_find_property(np, "#cooling-cells", NULL)) {
  -             cdev = of_cpufreq_cooling_register(np, cpu_present_mask);
  -             if (IS_ERR(cdev))
  -                     dev_err(cpu_dev,
  -                             "running cpufreq without cooling device: %ld\n",
  -                             PTR_ERR(cdev));
  -             else
  -                     priv->cdev = cdev;
  -     }
  -
        priv->cpu_dev = cpu_dev;
        priv->cpu_reg = cpu_reg;
        policy->driver_data = priv;
        if (ret) {
                dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__,
                        ret);
  -             goto out_cooling_unregister;
  +             goto out_free_cpufreq_table;
        }
   
        policy->cpuinfo.transition_latency = transition_latency;
   
        return 0;
   
  -out_cooling_unregister:
  -     cpufreq_cooling_unregister(priv->cdev);
  +out_free_cpufreq_table:
        dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
   out_free_priv:
        kfree(priv);
  -out_put_node:
  +out_free_opp:
  +     of_free_opp_table(cpu_dev);
        of_node_put(np);
   out_put_reg_clk:
        clk_put(cpu_clk);
@@@@ -309,10 -320,10 -319,8 +320,10 @@@@ static int cpufreq_exit(struct cpufreq_
   {
        struct private_data *priv = policy->driver_data;
   
  -     cpufreq_cooling_unregister(priv->cdev);
  +     if (priv->cdev)
  +             cpufreq_cooling_unregister(priv->cdev);
        dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
  +     of_free_opp_table(priv->cpu_dev);
        clk_put(policy->clk);
        if (!IS_ERR(priv->cpu_reg))
                regulator_put(priv->cpu_reg);
        return 0;
   }
   
  +static void cpufreq_ready(struct cpufreq_policy *policy)
  +{
  +     struct private_data *priv = policy->driver_data;
  +     struct device_node *np = of_node_get(priv->cpu_dev->of_node);
  +
  +     if (WARN_ON(!np))
  +             return;
  +
  +     /*
  +      * For now, just loading the cooling device;
  +      * thermal DT code takes care of matching them.
  +      */
  +     if (of_find_property(np, "#cooling-cells", NULL)) {
  +             priv->cdev = of_cpufreq_cooling_register(np,
  +                                                      policy->related_cpus);
  +             if (IS_ERR(priv->cdev)) {
  +                     dev_err(priv->cpu_dev,
  +                             "running cpufreq without cooling device: %ld\n",
  +                             PTR_ERR(priv->cdev));
  +
  +                     priv->cdev = NULL;
  +             }
  +     }
  +
  +     of_node_put(np);
  +}
  +
   static struct cpufreq_driver dt_cpufreq_driver = {
        .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
        .verify = cpufreq_generic_frequency_table_verify,
        .get = cpufreq_generic_get,
        .init = cpufreq_init,
        .exit = cpufreq_exit,
  +     .ready = cpufreq_ready,
        .name = "cpufreq-dt",
        .attr = cpufreq_generic_attr,
   };
@@@@ -400,6 -411,7 -380,7 +411,6 @@@@ static int dt_cpufreq_remove(struct pla
   static struct platform_driver dt_cpufreq_platdrv = {
        .driver = {
                .name   = "cpufreq-dt",
 --             .owner  = THIS_MODULE,
        },
        .probe          = dt_cpufreq_probe,
        .remove         = dt_cpufreq_remove,