| 1 | |
| 2 | |
| 3 | * Scheduler code and data structures related to cpufreq.
|
| 4 | *
|
| 5 | * Copyright (C) 2016, Intel Corporation
|
| 6 | * Author: Rafael J. Wysocki <[email protected]>
|
| 7 |
|
| 8 | #include "sched.h"
|
| 9 |
|
| 10 | DEFINE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
|
| 11 |
|
| 12 | |
| 13 | * cpufreq_add_update_util_hook - Populate the CPU's update_util_data pointer.
|
| 14 | * @cpu: The CPU to set the pointer for.
|
| 15 | * @data: New pointer value.
|
| 16 | * @func: Callback function to set for the CPU.
|
| 17 | *
|
| 18 | * Set and publish the update_util_data pointer for the given CPU.
|
| 19 | *
|
| 20 | * The update_util_data pointer of @cpu is set to @data and the callback
|
| 21 | * function pointer in the target struct update_util_data is set to @func.
|
| 22 | * That function will be called by cpufreq_update_util() from RCU-sched
|
| 23 | * read-side critical sections, so it must not sleep. @data will always be
|
| 24 | * passed to it as the first argument which allows the function to get to the
|
| 25 | * target update_util_data structure and its container.
|
| 26 | *
|
| 27 | * The update_util_data pointer of @cpu must be NULL when this function is
|
| 28 | * called or it will WARN() and return with no effect.
|
| 29 |
|
| 30 | void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
|
| 31 | void (*func)(struct update_util_data *data, u64 time,
|
| 32 | unsigned int flags))
|
| 33 | {
|
| 34 | if (WARN_ON(!data || !func))
|
| 35 | return;
|
| 36 |
|
| 37 | if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
|
| 38 | return;
|
| 39 |
|
| 40 | data->func = func;
|
| 41 | rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);
|
| 42 | }
|
| 43 | EXPORT_SYMBOL_GPL(cpufreq_add_update_util_hook);
|
| 44 |
|
| 45 | |
| 46 | * cpufreq_remove_update_util_hook - Clear the CPU's update_util_data pointer.
|
| 47 | * @cpu: The CPU to clear the pointer for.
|
| 48 | *
|
| 49 | * Clear the update_util_data pointer for the given CPU.
|
| 50 | *
|
| 51 | * Callers must use RCU callbacks to free any memory that might be
|
| 52 | * accessed via the old update_util_data pointer or invoke synchronize_rcu()
|
| 53 | * right after this function to avoid use-after-free.
|
| 54 |
|
| 55 | void cpufreq_remove_update_util_hook(int cpu)
|
| 56 | {
|
| 57 | rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), NULL);
|
| 58 | }
|
| 59 | EXPORT_SYMBOL_GPL(cpufreq_remove_update_util_hook);
|
| 60 |
|
| 61 | |
| 62 | * cpufreq_this_cpu_can_update - Check if cpufreq policy can be updated.
|
| 63 | * @policy: cpufreq policy to check.
|
| 64 | *
|
| 65 | * Return 'true' if:
|
| 66 | * - the local and remote CPUs share @policy,
|
| 67 | * - dvfs_possible_from_any_cpu is set in @policy and the local CPU is not going
|
| 68 | * offline (in which case it is not expected to run cpufreq updates any more).
|
| 69 |
|
| 70 | bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy)
|
| 71 | {
|
| 72 | return cpumask_test_cpu(smp_processor_id(), policy->cpus) ||
|
| 73 | (policy->dvfs_possible_from_any_cpu &&
|
| 74 | rcu_dereference_sched(*this_cpu_ptr(&cpufreq_update_util_data)));
|
| 75 | }
|