Merge tag 'docs-4.9' of git://git.lwn.net/linux
[cascardo/linux.git] / drivers / cpufreq / cpufreq.c
index 5617c70..6e6c1fb 100644 (file)
@@ -74,19 +74,12 @@ static inline bool has_target(void)
 }
 
 /* internal prototypes */
-static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
 static unsigned int __cpufreq_get(struct cpufreq_policy *policy);
+static int cpufreq_init_governor(struct cpufreq_policy *policy);
+static void cpufreq_exit_governor(struct cpufreq_policy *policy);
 static int cpufreq_start_governor(struct cpufreq_policy *policy);
-
-static inline void cpufreq_exit_governor(struct cpufreq_policy *policy)
-{
-       (void)cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
-}
-
-static inline void cpufreq_stop_governor(struct cpufreq_policy *policy)
-{
-       (void)cpufreq_governor(policy, CPUFREQ_GOV_STOP);
-}
+static void cpufreq_stop_governor(struct cpufreq_policy *policy);
+static void cpufreq_governor_limits(struct cpufreq_policy *policy);
 
 /**
  * Two notifier lists: the "policy" list is involved in the
@@ -133,15 +126,6 @@ struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)
 }
 EXPORT_SYMBOL_GPL(get_governor_parent_kobj);
 
-struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
-{
-       struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
-
-       return policy && !policy_is_inactive(policy) ?
-               policy->freq_table : NULL;
-}
-EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
-
 static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
 {
        u64 idle_time;
@@ -354,6 +338,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
                pr_debug("FREQ: %lu - CPU: %lu\n",
                         (unsigned long)freqs->new, (unsigned long)freqs->cpu);
                trace_cpu_frequency(freqs->new, freqs->cpu);
+               cpufreq_stats_record_transition(policy, freqs->new);
                srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
                                CPUFREQ_POSTCHANGE, freqs);
                if (likely(policy) && likely(policy->cpu == freqs->cpu))
@@ -507,6 +492,38 @@ void cpufreq_disable_fast_switch(struct cpufreq_policy *policy)
 }
 EXPORT_SYMBOL_GPL(cpufreq_disable_fast_switch);
 
+/**
+ * cpufreq_driver_resolve_freq - Map a target frequency to a driver-supported
+ * one.
+ * @target_freq: target frequency to resolve.
+ *
+ * The target to driver frequency mapping is cached in the policy.
+ *
+ * Return: Lowest driver-supported frequency greater than or equal to the
+ * given target_freq, subject to policy (min/max) and driver limitations.
+ */
+unsigned int cpufreq_driver_resolve_freq(struct cpufreq_policy *policy,
+                                        unsigned int target_freq)
+{
+       target_freq = clamp_val(target_freq, policy->min, policy->max);
+       policy->cached_target_freq = target_freq;
+
+       if (cpufreq_driver->target_index) {
+               int idx;
+
+               idx = cpufreq_frequency_table_target(policy, target_freq,
+                                                    CPUFREQ_RELATION_L);
+               policy->cached_resolved_idx = idx;
+               return policy->freq_table[idx].frequency;
+       }
+
+       if (cpufreq_driver->resolve_freq)
+               return cpufreq_driver->resolve_freq(policy, target_freq);
+
+       return target_freq;
+}
+EXPORT_SYMBOL_GPL(cpufreq_driver_resolve_freq);
+
 /*********************************************************************
  *                          SYSFS INTERFACE                          *
  *********************************************************************/
@@ -899,58 +916,18 @@ static struct kobj_type ktype_cpufreq = {
        .release        = cpufreq_sysfs_release,
 };
 
-static int add_cpu_dev_symlink(struct cpufreq_policy *policy, int cpu)
+static int add_cpu_dev_symlink(struct cpufreq_policy *policy,
+                              struct device *dev)
 {
-       struct device *cpu_dev;
-
-       pr_debug("%s: Adding symlink for CPU: %u\n", __func__, cpu);
-
-       if (!policy)
-               return 0;
-
-       cpu_dev = get_cpu_device(cpu);
-       if (WARN_ON(!cpu_dev))
-               return 0;
-
-       return sysfs_create_link(&cpu_dev->kobj, &policy->kobj, "cpufreq");
+       dev_dbg(dev, "%s: Adding symlink\n", __func__);
+       return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
 }
 
-static void remove_cpu_dev_symlink(struct cpufreq_policy *policy, int cpu)
+static void remove_cpu_dev_symlink(struct cpufreq_policy *policy,
+                                  struct device *dev)
 {
-       struct device *cpu_dev;
-
-       pr_debug("%s: Removing symlink for CPU: %u\n", __func__, cpu);
-
-       cpu_dev = get_cpu_device(cpu);
-       if (WARN_ON(!cpu_dev))
-               return;
-
-       sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
-}
-
-/* Add/remove symlinks for all related CPUs */
-static int cpufreq_add_dev_symlink(struct cpufreq_policy *policy)
-{
-       unsigned int j;
-       int ret = 0;
-
-       /* Some related CPUs might not be present (physically hotplugged) */
-       for_each_cpu(j, policy->real_cpus) {
-               ret = add_cpu_dev_symlink(policy, j);
-               if (ret)
-                       break;
-       }
-
-       return ret;
-}
-
-static void cpufreq_remove_dev_symlink(struct cpufreq_policy *policy)
-{
-       unsigned int j;
-
-       /* Some related CPUs might not be present (physically hotplugged) */
-       for_each_cpu(j, policy->real_cpus)
-               remove_cpu_dev_symlink(policy, j);
+       dev_dbg(dev, "%s: Removing symlink\n", __func__);
+       sysfs_remove_link(&dev->kobj, "cpufreq");
 }
 
 static int cpufreq_add_dev_interface(struct cpufreq_policy *policy)
@@ -982,7 +959,7 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy)
                        return ret;
        }
 
-       return cpufreq_add_dev_symlink(policy);
+       return 0;
 }
 
 __weak struct cpufreq_governor *cpufreq_default_governor(void)
@@ -1056,13 +1033,9 @@ static void handle_update(struct work_struct *work)
 
 static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
 {
-       struct device *dev = get_cpu_device(cpu);
        struct cpufreq_policy *policy;
        int ret;
 
-       if (WARN_ON(!dev))
-               return NULL;
-
        policy = kzalloc(sizeof(*policy), GFP_KERNEL);
        if (!policy)
                return NULL;
@@ -1115,7 +1088,7 @@ static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy, bool notify)
                                             CPUFREQ_REMOVE_POLICY, policy);
 
        down_write(&policy->rwsem);
-       cpufreq_remove_dev_symlink(policy);
+       cpufreq_stats_free_table(policy);
        kobj = &policy->kobj;
        cmp = &policy->kobj_unregister;
        up_write(&policy->rwsem);
@@ -1197,8 +1170,8 @@ static int cpufreq_online(unsigned int cpu)
        if (new_policy) {
                /* related_cpus should at least include policy->cpus. */
                cpumask_copy(policy->related_cpus, policy->cpus);
-               /* Remember CPUs present at the policy creation time. */
-               cpumask_and(policy->real_cpus, policy->cpus, cpu_present_mask);
+               /* Clear mask of registered CPUs */
+               cpumask_clear(policy->real_cpus);
        }
 
        /*
@@ -1265,13 +1238,12 @@ static int cpufreq_online(unsigned int cpu)
                }
        }
 
-       blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
-                                    CPUFREQ_START, policy);
-
        if (new_policy) {
                ret = cpufreq_add_dev_interface(policy);
                if (ret)
                        goto out_exit_policy;
+
+               cpufreq_stats_create_table(policy);
                blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
                                CPUFREQ_CREATE_POLICY, policy);
 
@@ -1280,6 +1252,9 @@ static int cpufreq_online(unsigned int cpu)
                write_unlock_irqrestore(&cpufreq_driver_lock, flags);
        }
 
+       blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+                                    CPUFREQ_START, policy);
+
        ret = cpufreq_init_policy(policy);
        if (ret) {
                pr_err("%s: Failed to initialize policy for cpu: %d (%d)\n",
@@ -1311,6 +1286,8 @@ out_free_policy:
        return ret;
 }
 
+static int cpufreq_offline(unsigned int cpu);
+
 /**
  * cpufreq_add_dev - the cpufreq interface for a CPU device.
  * @dev: CPU device.
@@ -1320,25 +1297,31 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 {
        struct cpufreq_policy *policy;
        unsigned cpu = dev->id;
+       int ret;
 
        dev_dbg(dev, "%s: adding CPU%u\n", __func__, cpu);
 
-       if (cpu_online(cpu))
-               return cpufreq_online(cpu);
+       if (cpu_online(cpu)) {
+               ret = cpufreq_online(cpu);
+               if (ret)
+                       return ret;
+       }
 
-       /*
-        * A hotplug notifier will follow and we will handle it as CPU online
-        * then.  For now, just create the sysfs link, unless there is no policy
-        * or the link is already present.
-        */
+       /* Create sysfs link on CPU registration */
        policy = per_cpu(cpufreq_cpu_data, cpu);
        if (!policy || cpumask_test_and_set_cpu(cpu, policy->real_cpus))
                return 0;
 
-       return add_cpu_dev_symlink(policy, cpu);
+       ret = add_cpu_dev_symlink(policy, dev);
+       if (ret) {
+               cpumask_clear_cpu(cpu, policy->real_cpus);
+               cpufreq_offline(cpu);
+       }
+
+       return ret;
 }
 
-static void cpufreq_offline(unsigned int cpu)
+static int cpufreq_offline(unsigned int cpu)
 {
        struct cpufreq_policy *policy;
        int ret;
@@ -1348,7 +1331,7 @@ static void cpufreq_offline(unsigned int cpu)
        policy = cpufreq_cpu_get_raw(cpu);
        if (!policy) {
                pr_debug("%s: No cpu_data found\n", __func__);
-               return;
+               return 0;
        }
 
        down_write(&policy->rwsem);
@@ -1397,6 +1380,7 @@ static void cpufreq_offline(unsigned int cpu)
 
 unlock:
        up_write(&policy->rwsem);
+       return 0;
 }
 
 /**
@@ -1416,7 +1400,7 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
                cpufreq_offline(cpu);
 
        cpumask_clear_cpu(cpu, policy->real_cpus);
-       remove_cpu_dev_symlink(policy, cpu);
+       remove_cpu_dev_symlink(policy, dev);
 
        if (cpumask_empty(policy->real_cpus))
                cpufreq_policy_free(policy, true);
@@ -1556,9 +1540,6 @@ static unsigned int cpufreq_update_current_freq(struct cpufreq_policy *policy)
 {
        unsigned int new_freq;
 
-       if (cpufreq_suspended)
-               return 0;
-
        new_freq = cpufreq_driver->get(policy->cpu);
        if (!new_freq)
                return 0;
@@ -1864,14 +1845,17 @@ static int __target_intermediate(struct cpufreq_policy *policy,
        return ret;
 }
 
-static int __target_index(struct cpufreq_policy *policy,
-                         struct cpufreq_frequency_table *freq_table, int index)
+static int __target_index(struct cpufreq_policy *policy, int index)
 {
        struct cpufreq_freqs freqs = {.old = policy->cur, .flags = 0};
        unsigned int intermediate_freq = 0;
+       unsigned int newfreq = policy->freq_table[index].frequency;
        int retval = -EINVAL;
        bool notify;
 
+       if (newfreq == policy->cur)
+               return 0;
+
        notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION);
        if (notify) {
                /* Handle switching to intermediate frequency */
@@ -1886,7 +1870,7 @@ static int __target_index(struct cpufreq_policy *policy,
                                freqs.old = freqs.new;
                }
 
-               freqs.new = freq_table[index].frequency;
+               freqs.new = newfreq;
                pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n",
                         __func__, policy->cpu, freqs.old, freqs.new);
 
@@ -1923,17 +1907,13 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
                            unsigned int relation)
 {
        unsigned int old_target_freq = target_freq;
-       struct cpufreq_frequency_table *freq_table;
-       int index, retval;
+       int index;
 
        if (cpufreq_disabled())
                return -ENODEV;
 
        /* Make sure that target_freq is within supported range */
-       if (target_freq > policy->max)
-               target_freq = policy->max;
-       if (target_freq < policy->min)
-               target_freq = policy->min;
+       target_freq = clamp_val(target_freq, policy->min, policy->max);
 
        pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
                 policy->cpu, target_freq, relation, old_target_freq);
@@ -1956,23 +1936,9 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
        if (!cpufreq_driver->target_index)
                return -EINVAL;
 
-       freq_table = cpufreq_frequency_get_table(policy->cpu);
-       if (unlikely(!freq_table)) {
-               pr_err("%s: Unable to find freq_table\n", __func__);
-               return -EINVAL;
-       }
-
-       retval = cpufreq_frequency_table_target(policy, freq_table, target_freq,
-                                               relation, &index);
-       if (unlikely(retval)) {
-               pr_err("%s: Unable to find matching freq\n", __func__);
-               return retval;
-       }
-
-       if (freq_table[index].frequency == policy->cur)
-               return 0;
+       index = cpufreq_frequency_table_target(policy, target_freq, relation);
 
-       return __target_index(policy, freq_table, index);
+       return __target_index(policy, index);
 }
 EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
 
@@ -1997,7 +1963,7 @@ __weak struct cpufreq_governor *cpufreq_fallback_governor(void)
        return NULL;
 }
 
-static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
+static int cpufreq_init_governor(struct cpufreq_policy *policy)
 {
        int ret;
 
@@ -2025,36 +1991,82 @@ static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
                }
        }
 
-       if (event == CPUFREQ_GOV_POLICY_INIT)
-               if (!try_module_get(policy->governor->owner))
-                       return -EINVAL;
-
-       pr_debug("%s: for CPU %u, event %u\n", __func__, policy->cpu, event);
+       if (!try_module_get(policy->governor->owner))
+               return -EINVAL;
 
-       ret = policy->governor->governor(policy, event);
+       pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
 
-       if (event == CPUFREQ_GOV_POLICY_INIT) {
-               if (ret)
+       if (policy->governor->init) {
+               ret = policy->governor->init(policy);
+               if (ret) {
                        module_put(policy->governor->owner);
-               else
-                       policy->governor->initialized++;
-       } else if (event == CPUFREQ_GOV_POLICY_EXIT) {
-               policy->governor->initialized--;
-               module_put(policy->governor->owner);
+                       return ret;
+               }
        }
 
-       return ret;
+       return 0;
+}
+
+static void cpufreq_exit_governor(struct cpufreq_policy *policy)
+{
+       if (cpufreq_suspended || !policy->governor)
+               return;
+
+       pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
+
+       if (policy->governor->exit)
+               policy->governor->exit(policy);
+
+       module_put(policy->governor->owner);
 }
 
 static int cpufreq_start_governor(struct cpufreq_policy *policy)
 {
        int ret;
 
+       if (cpufreq_suspended)
+               return 0;
+
+       if (!policy->governor)
+               return -EINVAL;
+
+       pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
+
        if (cpufreq_driver->get && !cpufreq_driver->setpolicy)
                cpufreq_update_current_freq(policy);
 
-       ret = cpufreq_governor(policy, CPUFREQ_GOV_START);
-       return ret ? ret : cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
+       if (policy->governor->start) {
+               ret = policy->governor->start(policy);
+               if (ret)
+                       return ret;
+       }
+
+       if (policy->governor->limits)
+               policy->governor->limits(policy);
+
+       return 0;
+}
+
+static void cpufreq_stop_governor(struct cpufreq_policy *policy)
+{
+       if (cpufreq_suspended || !policy->governor)
+               return;
+
+       pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
+
+       if (policy->governor->stop)
+               policy->governor->stop(policy);
+}
+
+static void cpufreq_governor_limits(struct cpufreq_policy *policy)
+{
+       if (cpufreq_suspended || !policy->governor)
+               return;
+
+       pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
+
+       if (policy->governor->limits)
+               policy->governor->limits(policy);
 }
 
 int cpufreq_register_governor(struct cpufreq_governor *governor)
@@ -2069,7 +2081,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
 
        mutex_lock(&cpufreq_governor_mutex);
 
-       governor->initialized = 0;
        err = -EBUSY;
        if (!find_governor(governor->name)) {
                err = 0;
@@ -2184,6 +2195,8 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
        policy->min = new_policy->min;
        policy->max = new_policy->max;
 
+       policy->cached_target_freq = UINT_MAX;
+
        pr_debug("new min and max freqs are %u - %u kHz\n",
                 policy->min, policy->max);
 
@@ -2195,7 +2208,8 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
 
        if (new_policy->governor == policy->governor) {
                pr_debug("cpufreq: governor limits update\n");
-               return cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
+               cpufreq_governor_limits(policy);
+               return 0;
        }
 
        pr_debug("governor switch\n");
@@ -2210,7 +2224,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
 
        /* start new governor */
        policy->governor = new_policy->governor;
-       ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
+       ret = cpufreq_init_governor(policy);
        if (!ret) {
                ret = cpufreq_start_governor(policy);
                if (!ret) {
@@ -2224,7 +2238,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
        pr_debug("starting governor %s failed\n", policy->governor->name);
        if (old_gov) {
                policy->governor = old_gov;
-               if (cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT))
+               if (cpufreq_init_governor(policy))
                        policy->governor = NULL;
                else
                        cpufreq_start_governor(policy);
@@ -2282,53 +2296,30 @@ unlock:
 }
 EXPORT_SYMBOL(cpufreq_update_policy);
 
-static int cpufreq_cpu_callback(struct notifier_block *nfb,
-                                       unsigned long action, void *hcpu)
-{
-       unsigned int cpu = (unsigned long)hcpu;
-
-       switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_ONLINE:
-       case CPU_DOWN_FAILED:
-               cpufreq_online(cpu);
-               break;
-
-       case CPU_DOWN_PREPARE:
-               cpufreq_offline(cpu);
-               break;
-       }
-       return NOTIFY_OK;
-}
-
-static struct notifier_block __refdata cpufreq_cpu_notifier = {
-       .notifier_call = cpufreq_cpu_callback,
-};
-
 /*********************************************************************
  *               BOOST                                              *
  *********************************************************************/
 static int cpufreq_boost_set_sw(int state)
 {
-       struct cpufreq_frequency_table *freq_table;
        struct cpufreq_policy *policy;
        int ret = -EINVAL;
 
        for_each_active_policy(policy) {
-               freq_table = cpufreq_frequency_get_table(policy->cpu);
-               if (freq_table) {
-                       ret = cpufreq_frequency_table_cpuinfo(policy,
-                                                       freq_table);
-                       if (ret) {
-                               pr_err("%s: Policy frequency update failed\n",
-                                      __func__);
-                               break;
-                       }
-
-                       down_write(&policy->rwsem);
-                       policy->user_policy.max = policy->max;
-                       cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
-                       up_write(&policy->rwsem);
+               if (!policy->freq_table)
+                       continue;
+
+               ret = cpufreq_frequency_table_cpuinfo(policy,
+                                                     policy->freq_table);
+               if (ret) {
+                       pr_err("%s: Policy frequency update failed\n",
+                              __func__);
+                       break;
                }
+
+               down_write(&policy->rwsem);
+               policy->user_policy.max = policy->max;
+               cpufreq_governor_limits(policy);
+               up_write(&policy->rwsem);
        }
 
        return ret;
@@ -2406,6 +2397,7 @@ EXPORT_SYMBOL_GPL(cpufreq_boost_enabled);
 /*********************************************************************
  *               REGISTER / UNREGISTER CPUFREQ DRIVER                *
  *********************************************************************/
+static enum cpuhp_state hp_online;
 
 /**
  * cpufreq_register_driver - register a CPU Frequency driver
@@ -2468,7 +2460,14 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
                goto err_if_unreg;
        }
 
-       register_hotcpu_notifier(&cpufreq_cpu_notifier);
+       ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "cpufreq:online",
+                                       cpufreq_online,
+                                       cpufreq_offline);
+       if (ret < 0)
+               goto err_if_unreg;
+       hp_online = ret;
+       ret = 0;
+
        pr_debug("driver %s up and running\n", driver_data->name);
        goto out;
 
@@ -2507,7 +2506,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
        get_online_cpus();
        subsys_interface_unregister(&cpufreq_interface);
        remove_boost_sysfs_file();
-       unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
+       cpuhp_remove_state_nocalls(hp_online);
 
        write_lock_irqsave(&cpufreq_driver_lock, flags);