You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'pm-cpufreq'
* pm-cpufreq: (41 commits) Revert "cpufreq: pcc-cpufreq: update default value of cpuinfo_transition_latency" cpufreq: export cpufreq_driver_resolve_freq() cpufreq: Disallow ->resolve_freq() for drivers providing ->target_index() cpufreq: acpi-cpufreq: use cached frequency mapping when possible cpufreq: schedutil: map raw required frequency to driver frequency cpufreq: add cpufreq_driver_resolve_freq() cpufreq: intel_pstate: Check cpuid for MSR_HWP_INTERRUPT intel_pstate: Update cpu_frequency tracepoint every time cpufreq: intel_pstate: clean remnant struct element cpufreq: powernv: Replacing pstate_id with frequency table index intel_pstate: Fix MSR_CONFIG_TDP_x addressing in core_get_max_pstate() cpufreq: Reuse new freq-table helpers cpufreq: Handle sorted frequency tables more efficiently cpufreq: Drop redundant check from cpufreq_update_current_freq() intel_pstate: Declare pid_params/pstate_funcs/hwp_active __read_mostly intel_pstate: add __init/__initdata marker to some functions/variables intel_pstate: Fix incorrect placement of __initdata cpufreq: mvebu: fix integer to pointer cast cpufreq: intel_pstate: Broxton support cpufreq: conservative: Do not use transition notifications ...
This commit is contained in:
@@ -96,7 +96,7 @@ new - new frequency
|
||||
For details about OPP, see Documentation/power/opp.txt
|
||||
|
||||
dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with
|
||||
cpufreq_frequency_table_cpuinfo which is provided with the list of
|
||||
cpufreq_table_validate_and_show() which is provided with the list of
|
||||
frequencies that are available for operation. This function provides
|
||||
a ready to use conversion routine to translate the OPP layer's internal
|
||||
information about the available frequencies into a format readily
|
||||
@@ -110,7 +110,7 @@ dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with
|
||||
/* Do things */
|
||||
r = dev_pm_opp_init_cpufreq_table(dev, &freq_table);
|
||||
if (!r)
|
||||
cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
cpufreq_table_validate_and_show(policy, freq_table);
|
||||
/* Do other things */
|
||||
}
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ if you want to skip one entry in the table, set the frequency to
|
||||
CPUFREQ_ENTRY_INVALID. The entries don't need to be in ascending
|
||||
order.
|
||||
|
||||
By calling cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
|
||||
By calling cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
|
||||
struct cpufreq_frequency_table *table);
|
||||
the cpuinfo.min_freq and cpuinfo.max_freq values are detected, and
|
||||
policy->min and policy->max are set to the same values. This is
|
||||
@@ -244,14 +244,12 @@ policy->max, and all other criteria are met. This is helpful for the
|
||||
->verify call.
|
||||
|
||||
int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
||||
struct cpufreq_frequency_table *table,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation,
|
||||
unsigned int *index);
|
||||
unsigned int relation);
|
||||
|
||||
is the corresponding frequency table helper for the ->target
|
||||
stage. Just pass the values to this function, and the unsigned int
|
||||
index returns the number of the frequency table entry which contains
|
||||
stage. Just pass the values to this function, and this function
|
||||
returns the number of the frequency table entry which contains
|
||||
the frequency the CPU shall be set to.
|
||||
|
||||
The following macros can be used as iterators over cpufreq_frequency_table:
|
||||
|
||||
@@ -159,8 +159,8 @@ to be strictly associated with a P-state.
|
||||
|
||||
2.2 cpuinfo_transition_latency:
|
||||
-------------------------------
|
||||
The cpuinfo_transition_latency field is CPUFREQ_ETERNAL. The PCC specification
|
||||
does not include a field to expose this value currently.
|
||||
The cpuinfo_transition_latency field is 0. The PCC specification does
|
||||
not include a field to expose this value currently.
|
||||
|
||||
2.3 cpuinfo_cur_freq:
|
||||
---------------------
|
||||
|
||||
@@ -85,61 +85,57 @@ static void spu_gov_cancel_work(struct spu_gov_info_struct *info)
|
||||
cancel_delayed_work_sync(&info->work);
|
||||
}
|
||||
|
||||
static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
|
||||
static int spu_gov_start(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned int cpu = policy->cpu;
|
||||
struct spu_gov_info_struct *info, *affected_info;
|
||||
struct spu_gov_info_struct *info = &per_cpu(spu_gov_info, cpu);
|
||||
struct spu_gov_info_struct *affected_info;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
info = &per_cpu(spu_gov_info, cpu);
|
||||
|
||||
switch (event) {
|
||||
case CPUFREQ_GOV_START:
|
||||
if (!cpu_online(cpu)) {
|
||||
printk(KERN_ERR "cpu %d is not online\n", cpu);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!policy->cur) {
|
||||
printk(KERN_ERR "no cpu specified in policy\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* initialize spu_gov_info for all affected cpus */
|
||||
for_each_cpu(i, policy->cpus) {
|
||||
affected_info = &per_cpu(spu_gov_info, i);
|
||||
affected_info->policy = policy;
|
||||
}
|
||||
|
||||
info->poll_int = POLL_TIME;
|
||||
|
||||
/* setup timer */
|
||||
spu_gov_init_work(info);
|
||||
|
||||
break;
|
||||
|
||||
case CPUFREQ_GOV_STOP:
|
||||
/* cancel timer */
|
||||
spu_gov_cancel_work(info);
|
||||
|
||||
/* clean spu_gov_info for all affected cpus */
|
||||
for_each_cpu (i, policy->cpus) {
|
||||
info = &per_cpu(spu_gov_info, i);
|
||||
info->policy = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
if (!cpu_online(cpu)) {
|
||||
printk(KERN_ERR "cpu %d is not online\n", cpu);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (!policy->cur) {
|
||||
printk(KERN_ERR "no cpu specified in policy\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* initialize spu_gov_info for all affected cpus */
|
||||
for_each_cpu(i, policy->cpus) {
|
||||
affected_info = &per_cpu(spu_gov_info, i);
|
||||
affected_info->policy = policy;
|
||||
}
|
||||
|
||||
info->poll_int = POLL_TIME;
|
||||
|
||||
/* setup timer */
|
||||
spu_gov_init_work(info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spu_gov_stop(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned int cpu = policy->cpu;
|
||||
struct spu_gov_info_struct *info = &per_cpu(spu_gov_info, cpu);
|
||||
int i;
|
||||
|
||||
/* cancel timer */
|
||||
spu_gov_cancel_work(info);
|
||||
|
||||
/* clean spu_gov_info for all affected cpus */
|
||||
for_each_cpu (i, policy->cpus) {
|
||||
info = &per_cpu(spu_gov_info, i);
|
||||
info->policy = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct cpufreq_governor spu_governor = {
|
||||
.name = "spudemand",
|
||||
.governor = spu_gov_govern,
|
||||
.start = spu_gov_start,
|
||||
.stop = spu_gov_stop,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
@@ -31,23 +31,18 @@ config CPU_FREQ_BOOST_SW
|
||||
depends on THERMAL
|
||||
|
||||
config CPU_FREQ_STAT
|
||||
tristate "CPU frequency translation statistics"
|
||||
bool "CPU frequency transition statistics"
|
||||
default y
|
||||
help
|
||||
This driver exports CPU frequency statistics information through sysfs
|
||||
file system.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cpufreq_stats.
|
||||
Export CPU frequency statistics information through sysfs.
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
config CPU_FREQ_STAT_DETAILS
|
||||
bool "CPU frequency translation statistics details"
|
||||
bool "CPU frequency transition statistics details"
|
||||
depends on CPU_FREQ_STAT
|
||||
help
|
||||
This will show detail CPU frequency translation table in sysfs file
|
||||
system.
|
||||
Show detailed CPU frequency transition table in sysfs.
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
|
||||
@@ -468,20 +468,17 @@ unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy,
|
||||
struct acpi_cpufreq_data *data = policy->driver_data;
|
||||
struct acpi_processor_performance *perf;
|
||||
struct cpufreq_frequency_table *entry;
|
||||
unsigned int next_perf_state, next_freq, freq;
|
||||
unsigned int next_perf_state, next_freq, index;
|
||||
|
||||
/*
|
||||
* Find the closest frequency above target_freq.
|
||||
*
|
||||
* The table is sorted in the reverse order with respect to the
|
||||
* frequency and all of the entries are valid (see the initialization).
|
||||
*/
|
||||
entry = policy->freq_table;
|
||||
do {
|
||||
entry++;
|
||||
freq = entry->frequency;
|
||||
} while (freq >= target_freq && freq != CPUFREQ_TABLE_END);
|
||||
entry--;
|
||||
if (policy->cached_target_freq == target_freq)
|
||||
index = policy->cached_resolved_idx;
|
||||
else
|
||||
index = cpufreq_table_find_index_dl(policy, target_freq);
|
||||
|
||||
entry = &policy->freq_table[index];
|
||||
next_freq = entry->frequency;
|
||||
next_perf_state = entry->driver_data;
|
||||
|
||||
|
||||
@@ -48,9 +48,8 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy,
|
||||
struct policy_dbs_info *policy_dbs = policy->governor_data;
|
||||
struct dbs_data *od_data = policy_dbs->dbs_data;
|
||||
struct od_dbs_tuners *od_tuners = od_data->tuners;
|
||||
struct od_policy_dbs_info *od_info = to_dbs_info(policy_dbs);
|
||||
|
||||
if (!od_info->freq_table)
|
||||
if (!policy->freq_table)
|
||||
return freq_next;
|
||||
|
||||
rdmsr_on_cpu(policy->cpu, MSR_AMD64_FREQ_SENSITIVITY_ACTUAL,
|
||||
@@ -92,10 +91,9 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy,
|
||||
else {
|
||||
unsigned int index;
|
||||
|
||||
cpufreq_frequency_table_target(policy,
|
||||
od_info->freq_table, policy->cur - 1,
|
||||
CPUFREQ_RELATION_H, &index);
|
||||
freq_next = od_info->freq_table[index].frequency;
|
||||
index = cpufreq_table_find_index_h(policy,
|
||||
policy->cur - 1);
|
||||
freq_next = policy->freq_table[index].frequency;
|
||||
}
|
||||
|
||||
data->freq_prev = freq_next;
|
||||
|
||||
+135
-86
@@ -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 *
|
||||
*********************************************************************/
|
||||
@@ -1115,6 +1132,7 @@ static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy, bool notify)
|
||||
CPUFREQ_REMOVE_POLICY, policy);
|
||||
|
||||
down_write(&policy->rwsem);
|
||||
cpufreq_stats_free_table(policy);
|
||||
cpufreq_remove_dev_symlink(policy);
|
||||
kobj = &policy->kobj;
|
||||
cmp = &policy->kobj_unregister;
|
||||
@@ -1265,13 +1283,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 +1297,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",
|
||||
@@ -1556,9 +1576,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 +1881,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 +1906,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 +1943,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 +1972,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;
|
||||
}
|
||||
index = cpufreq_frequency_table_target(policy, target_freq, relation);
|
||||
|
||||
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;
|
||||
|
||||
return __target_index(policy, freq_table, index);
|
||||
return __target_index(policy, index);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
|
||||
|
||||
@@ -1997,7 +1999,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 +2027,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;
|
||||
if (!try_module_get(policy->governor->owner))
|
||||
return -EINVAL;
|
||||
|
||||
pr_debug("%s: for CPU %u, event %u\n", __func__, policy->cpu, event);
|
||||
pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
|
||||
|
||||
ret = policy->governor->governor(policy, event);
|
||||
|
||||
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 +2117,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 +2231,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 +2244,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 +2260,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 +2274,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);
|
||||
@@ -2309,26 +2359,25 @@ static struct notifier_block __refdata cpufreq_cpu_notifier = {
|
||||
*********************************************************************/
|
||||
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;
|
||||
}
|
||||
if (!policy->freq_table)
|
||||
continue;
|
||||
|
||||
down_write(&policy->rwsem);
|
||||
policy->user_policy.max = policy->max;
|
||||
cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
|
||||
up_write(&policy->rwsem);
|
||||
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;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
struct cs_policy_dbs_info {
|
||||
struct policy_dbs_info policy_dbs;
|
||||
unsigned int down_skip;
|
||||
unsigned int requested_freq;
|
||||
};
|
||||
|
||||
static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs)
|
||||
@@ -75,19 +74,17 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
|
||||
|
||||
/* Check for frequency increase */
|
||||
if (load > dbs_data->up_threshold) {
|
||||
unsigned int requested_freq = policy->cur;
|
||||
|
||||
dbs_info->down_skip = 0;
|
||||
|
||||
/* if we are already at full speed then break out early */
|
||||
if (dbs_info->requested_freq == policy->max)
|
||||
if (requested_freq == policy->max)
|
||||
goto out;
|
||||
|
||||
dbs_info->requested_freq += get_freq_target(cs_tuners, policy);
|
||||
requested_freq += get_freq_target(cs_tuners, policy);
|
||||
|
||||
if (dbs_info->requested_freq > policy->max)
|
||||
dbs_info->requested_freq = policy->max;
|
||||
|
||||
__cpufreq_driver_target(policy, dbs_info->requested_freq,
|
||||
CPUFREQ_RELATION_H);
|
||||
__cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_H);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -98,36 +95,27 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
|
||||
|
||||
/* Check for frequency decrease */
|
||||
if (load < cs_tuners->down_threshold) {
|
||||
unsigned int freq_target;
|
||||
unsigned int freq_target, requested_freq = policy->cur;
|
||||
/*
|
||||
* if we cannot reduce the frequency anymore, break out early
|
||||
*/
|
||||
if (policy->cur == policy->min)
|
||||
if (requested_freq == policy->min)
|
||||
goto out;
|
||||
|
||||
freq_target = get_freq_target(cs_tuners, policy);
|
||||
if (dbs_info->requested_freq > freq_target)
|
||||
dbs_info->requested_freq -= freq_target;
|
||||
if (requested_freq > freq_target)
|
||||
requested_freq -= freq_target;
|
||||
else
|
||||
dbs_info->requested_freq = policy->min;
|
||||
requested_freq = policy->min;
|
||||
|
||||
__cpufreq_driver_target(policy, dbs_info->requested_freq,
|
||||
CPUFREQ_RELATION_L);
|
||||
__cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_L);
|
||||
}
|
||||
|
||||
out:
|
||||
return dbs_data->sampling_rate;
|
||||
}
|
||||
|
||||
static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
|
||||
void *data);
|
||||
|
||||
static struct notifier_block cs_cpufreq_notifier_block = {
|
||||
.notifier_call = dbs_cpufreq_notifier,
|
||||
};
|
||||
|
||||
/************************** sysfs interface ************************/
|
||||
static struct dbs_governor cs_dbs_gov;
|
||||
|
||||
static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
|
||||
const char *buf, size_t count)
|
||||
@@ -268,15 +256,13 @@ static void cs_free(struct policy_dbs_info *policy_dbs)
|
||||
kfree(to_dbs_info(policy_dbs));
|
||||
}
|
||||
|
||||
static int cs_init(struct dbs_data *dbs_data, bool notify)
|
||||
static int cs_init(struct dbs_data *dbs_data)
|
||||
{
|
||||
struct cs_dbs_tuners *tuners;
|
||||
|
||||
tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
|
||||
if (!tuners) {
|
||||
pr_err("%s: kzalloc failed\n", __func__);
|
||||
if (!tuners)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD;
|
||||
tuners->freq_step = DEF_FREQUENCY_STEP;
|
||||
@@ -288,19 +274,11 @@ static int cs_init(struct dbs_data *dbs_data, bool notify)
|
||||
dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
|
||||
jiffies_to_usecs(10);
|
||||
|
||||
if (notify)
|
||||
cpufreq_register_notifier(&cs_cpufreq_notifier_block,
|
||||
CPUFREQ_TRANSITION_NOTIFIER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cs_exit(struct dbs_data *dbs_data, bool notify)
|
||||
static void cs_exit(struct dbs_data *dbs_data)
|
||||
{
|
||||
if (notify)
|
||||
cpufreq_unregister_notifier(&cs_cpufreq_notifier_block,
|
||||
CPUFREQ_TRANSITION_NOTIFIER);
|
||||
|
||||
kfree(dbs_data->tuners);
|
||||
}
|
||||
|
||||
@@ -309,16 +287,10 @@ static void cs_start(struct cpufreq_policy *policy)
|
||||
struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
|
||||
|
||||
dbs_info->down_skip = 0;
|
||||
dbs_info->requested_freq = policy->cur;
|
||||
}
|
||||
|
||||
static struct dbs_governor cs_dbs_gov = {
|
||||
.gov = {
|
||||
.name = "conservative",
|
||||
.governor = cpufreq_governor_dbs,
|
||||
.max_transition_latency = TRANSITION_LATENCY_LIMIT,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
static struct dbs_governor cs_governor = {
|
||||
.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
|
||||
.kobj_type = { .default_attrs = cs_attributes },
|
||||
.gov_dbs_timer = cs_dbs_timer,
|
||||
.alloc = cs_alloc,
|
||||
@@ -328,33 +300,7 @@ static struct dbs_governor cs_dbs_gov = {
|
||||
.start = cs_start,
|
||||
};
|
||||
|
||||
#define CPU_FREQ_GOV_CONSERVATIVE (&cs_dbs_gov.gov)
|
||||
|
||||
static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
|
||||
void *data)
|
||||
{
|
||||
struct cpufreq_freqs *freq = data;
|
||||
struct cpufreq_policy *policy = cpufreq_cpu_get_raw(freq->cpu);
|
||||
struct cs_policy_dbs_info *dbs_info;
|
||||
|
||||
if (!policy)
|
||||
return 0;
|
||||
|
||||
/* policy isn't governed by conservative governor */
|
||||
if (policy->governor != CPU_FREQ_GOV_CONSERVATIVE)
|
||||
return 0;
|
||||
|
||||
dbs_info = to_dbs_info(policy->governor_data);
|
||||
/*
|
||||
* we only care if our internally tracked freq moves outside the 'valid'
|
||||
* ranges of frequency available to us otherwise we do not change it
|
||||
*/
|
||||
if (dbs_info->requested_freq > policy->max
|
||||
|| dbs_info->requested_freq < policy->min)
|
||||
dbs_info->requested_freq = freq->new;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define CPU_FREQ_GOV_CONSERVATIVE (&cs_governor.gov)
|
||||
|
||||
static int __init cpufreq_gov_dbs_init(void)
|
||||
{
|
||||
|
||||
@@ -336,17 +336,6 @@ static inline void gov_clear_update_util(struct cpufreq_policy *policy)
|
||||
synchronize_sched();
|
||||
}
|
||||
|
||||
static void gov_cancel_work(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct policy_dbs_info *policy_dbs = policy->governor_data;
|
||||
|
||||
gov_clear_update_util(policy_dbs->policy);
|
||||
irq_work_sync(&policy_dbs->irq_work);
|
||||
cancel_work_sync(&policy_dbs->work);
|
||||
atomic_set(&policy_dbs->work_count, 0);
|
||||
policy_dbs->work_in_progress = false;
|
||||
}
|
||||
|
||||
static struct policy_dbs_info *alloc_policy_dbs_info(struct cpufreq_policy *policy,
|
||||
struct dbs_governor *gov)
|
||||
{
|
||||
@@ -389,7 +378,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,
|
||||
gov->free(policy_dbs);
|
||||
}
|
||||
|
||||
static int cpufreq_governor_init(struct cpufreq_policy *policy)
|
||||
int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct dbs_governor *gov = dbs_governor_of(policy);
|
||||
struct dbs_data *dbs_data;
|
||||
@@ -429,7 +418,7 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
|
||||
|
||||
gov_attr_set_init(&dbs_data->attr_set, &policy_dbs->list);
|
||||
|
||||
ret = gov->init(dbs_data, !policy->governor->initialized);
|
||||
ret = gov->init(dbs_data);
|
||||
if (ret)
|
||||
goto free_policy_dbs_info;
|
||||
|
||||
@@ -458,13 +447,13 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
|
||||
goto out;
|
||||
|
||||
/* Failure, so roll back. */
|
||||
pr_err("cpufreq: Governor initialization failed (dbs_data kobject init error %d)\n", ret);
|
||||
pr_err("initialization failed (dbs_data kobject init error %d)\n", ret);
|
||||
|
||||
policy->governor_data = NULL;
|
||||
|
||||
if (!have_governor_per_policy())
|
||||
gov->gdbs_data = NULL;
|
||||
gov->exit(dbs_data, !policy->governor->initialized);
|
||||
gov->exit(dbs_data);
|
||||
kfree(dbs_data);
|
||||
|
||||
free_policy_dbs_info:
|
||||
@@ -474,8 +463,9 @@ out:
|
||||
mutex_unlock(&gov_dbs_data_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_init);
|
||||
|
||||
static int cpufreq_governor_exit(struct cpufreq_policy *policy)
|
||||
void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct dbs_governor *gov = dbs_governor_of(policy);
|
||||
struct policy_dbs_info *policy_dbs = policy->governor_data;
|
||||
@@ -493,17 +483,17 @@ static int cpufreq_governor_exit(struct cpufreq_policy *policy)
|
||||
if (!have_governor_per_policy())
|
||||
gov->gdbs_data = NULL;
|
||||
|
||||
gov->exit(dbs_data, policy->governor->initialized == 1);
|
||||
gov->exit(dbs_data);
|
||||
kfree(dbs_data);
|
||||
}
|
||||
|
||||
free_policy_dbs_info(policy_dbs, gov);
|
||||
|
||||
mutex_unlock(&gov_dbs_data_mutex);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_exit);
|
||||
|
||||
static int cpufreq_governor_start(struct cpufreq_policy *policy)
|
||||
int cpufreq_dbs_governor_start(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct dbs_governor *gov = dbs_governor_of(policy);
|
||||
struct policy_dbs_info *policy_dbs = policy->governor_data;
|
||||
@@ -539,47 +529,28 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy)
|
||||
gov_set_update_util(policy_dbs, sampling_rate);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_start);
|
||||
|
||||
static int cpufreq_governor_stop(struct cpufreq_policy *policy)
|
||||
void cpufreq_dbs_governor_stop(struct cpufreq_policy *policy)
|
||||
{
|
||||
gov_cancel_work(policy);
|
||||
return 0;
|
||||
}
|
||||
struct policy_dbs_info *policy_dbs = policy->governor_data;
|
||||
|
||||
static int cpufreq_governor_limits(struct cpufreq_policy *policy)
|
||||
gov_clear_update_util(policy_dbs->policy);
|
||||
irq_work_sync(&policy_dbs->irq_work);
|
||||
cancel_work_sync(&policy_dbs->work);
|
||||
atomic_set(&policy_dbs->work_count, 0);
|
||||
policy_dbs->work_in_progress = false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_stop);
|
||||
|
||||
void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct policy_dbs_info *policy_dbs = policy->governor_data;
|
||||
|
||||
mutex_lock(&policy_dbs->timer_mutex);
|
||||
|
||||
if (policy->max < policy->cur)
|
||||
__cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
|
||||
else if (policy->min > policy->cur)
|
||||
__cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
|
||||
|
||||
cpufreq_policy_apply_limits(policy);
|
||||
gov_update_sample_delay(policy_dbs, 0);
|
||||
|
||||
mutex_unlock(&policy_dbs->timer_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event)
|
||||
{
|
||||
if (event == CPUFREQ_GOV_POLICY_INIT) {
|
||||
return cpufreq_governor_init(policy);
|
||||
} else if (policy->governor_data) {
|
||||
switch (event) {
|
||||
case CPUFREQ_GOV_POLICY_EXIT:
|
||||
return cpufreq_governor_exit(policy);
|
||||
case CPUFREQ_GOV_START:
|
||||
return cpufreq_governor_start(policy);
|
||||
case CPUFREQ_GOV_STOP:
|
||||
return cpufreq_governor_stop(policy);
|
||||
case CPUFREQ_GOV_LIMITS:
|
||||
return cpufreq_governor_limits(policy);
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_governor_dbs);
|
||||
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_limits);
|
||||
|
||||
@@ -138,8 +138,8 @@ struct dbs_governor {
|
||||
unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy);
|
||||
struct policy_dbs_info *(*alloc)(void);
|
||||
void (*free)(struct policy_dbs_info *policy_dbs);
|
||||
int (*init)(struct dbs_data *dbs_data, bool notify);
|
||||
void (*exit)(struct dbs_data *dbs_data, bool notify);
|
||||
int (*init)(struct dbs_data *dbs_data);
|
||||
void (*exit)(struct dbs_data *dbs_data);
|
||||
void (*start)(struct cpufreq_policy *policy);
|
||||
};
|
||||
|
||||
@@ -148,6 +148,25 @@ static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy
|
||||
return container_of(policy->governor, struct dbs_governor, gov);
|
||||
}
|
||||
|
||||
/* Governor callback routines */
|
||||
int cpufreq_dbs_governor_init(struct cpufreq_policy *policy);
|
||||
void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy);
|
||||
int cpufreq_dbs_governor_start(struct cpufreq_policy *policy);
|
||||
void cpufreq_dbs_governor_stop(struct cpufreq_policy *policy);
|
||||
void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy);
|
||||
|
||||
#define CPUFREQ_DBS_GOVERNOR_INITIALIZER(_name_) \
|
||||
{ \
|
||||
.name = _name_, \
|
||||
.max_transition_latency = TRANSITION_LATENCY_LIMIT, \
|
||||
.owner = THIS_MODULE, \
|
||||
.init = cpufreq_dbs_governor_init, \
|
||||
.exit = cpufreq_dbs_governor_exit, \
|
||||
.start = cpufreq_dbs_governor_start, \
|
||||
.stop = cpufreq_dbs_governor_stop, \
|
||||
.limits = cpufreq_dbs_governor_limits, \
|
||||
}
|
||||
|
||||
/* Governor specific operations */
|
||||
struct od_ops {
|
||||
unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
|
||||
@@ -155,7 +174,6 @@ struct od_ops {
|
||||
};
|
||||
|
||||
unsigned int dbs_update(struct cpufreq_policy *policy);
|
||||
int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event);
|
||||
void od_register_powersave_bias_handler(unsigned int (*f)
|
||||
(struct cpufreq_policy *, unsigned int, unsigned int),
|
||||
unsigned int powersave_bias);
|
||||
|
||||
@@ -65,34 +65,30 @@ static unsigned int generic_powersave_bias_target(struct cpufreq_policy *policy,
|
||||
{
|
||||
unsigned int freq_req, freq_reduc, freq_avg;
|
||||
unsigned int freq_hi, freq_lo;
|
||||
unsigned int index = 0;
|
||||
unsigned int index;
|
||||
unsigned int delay_hi_us;
|
||||
struct policy_dbs_info *policy_dbs = policy->governor_data;
|
||||
struct od_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
|
||||
struct dbs_data *dbs_data = policy_dbs->dbs_data;
|
||||
struct od_dbs_tuners *od_tuners = dbs_data->tuners;
|
||||
struct cpufreq_frequency_table *freq_table = policy->freq_table;
|
||||
|
||||
if (!dbs_info->freq_table) {
|
||||
if (!freq_table) {
|
||||
dbs_info->freq_lo = 0;
|
||||
dbs_info->freq_lo_delay_us = 0;
|
||||
return freq_next;
|
||||
}
|
||||
|
||||
cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next,
|
||||
relation, &index);
|
||||
freq_req = dbs_info->freq_table[index].frequency;
|
||||
index = cpufreq_frequency_table_target(policy, freq_next, relation);
|
||||
freq_req = freq_table[index].frequency;
|
||||
freq_reduc = freq_req * od_tuners->powersave_bias / 1000;
|
||||
freq_avg = freq_req - freq_reduc;
|
||||
|
||||
/* Find freq bounds for freq_avg in freq_table */
|
||||
index = 0;
|
||||
cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg,
|
||||
CPUFREQ_RELATION_H, &index);
|
||||
freq_lo = dbs_info->freq_table[index].frequency;
|
||||
index = 0;
|
||||
cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg,
|
||||
CPUFREQ_RELATION_L, &index);
|
||||
freq_hi = dbs_info->freq_table[index].frequency;
|
||||
index = cpufreq_table_find_index_h(policy, freq_avg);
|
||||
freq_lo = freq_table[index].frequency;
|
||||
index = cpufreq_table_find_index_l(policy, freq_avg);
|
||||
freq_hi = freq_table[index].frequency;
|
||||
|
||||
/* Find out how long we have to be in hi and lo freqs */
|
||||
if (freq_hi == freq_lo) {
|
||||
@@ -113,7 +109,6 @@ static void ondemand_powersave_bias_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct od_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
|
||||
|
||||
dbs_info->freq_table = cpufreq_frequency_get_table(policy->cpu);
|
||||
dbs_info->freq_lo = 0;
|
||||
}
|
||||
|
||||
@@ -361,17 +356,15 @@ static void od_free(struct policy_dbs_info *policy_dbs)
|
||||
kfree(to_dbs_info(policy_dbs));
|
||||
}
|
||||
|
||||
static int od_init(struct dbs_data *dbs_data, bool notify)
|
||||
static int od_init(struct dbs_data *dbs_data)
|
||||
{
|
||||
struct od_dbs_tuners *tuners;
|
||||
u64 idle_time;
|
||||
int cpu;
|
||||
|
||||
tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
|
||||
if (!tuners) {
|
||||
pr_err("%s: kzalloc failed\n", __func__);
|
||||
if (!tuners)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cpu = get_cpu();
|
||||
idle_time = get_cpu_idle_time_us(cpu, NULL);
|
||||
@@ -402,7 +395,7 @@ static int od_init(struct dbs_data *dbs_data, bool notify)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void od_exit(struct dbs_data *dbs_data, bool notify)
|
||||
static void od_exit(struct dbs_data *dbs_data)
|
||||
{
|
||||
kfree(dbs_data->tuners);
|
||||
}
|
||||
@@ -420,12 +413,7 @@ static struct od_ops od_ops = {
|
||||
};
|
||||
|
||||
static struct dbs_governor od_dbs_gov = {
|
||||
.gov = {
|
||||
.name = "ondemand",
|
||||
.governor = cpufreq_governor_dbs,
|
||||
.max_transition_latency = TRANSITION_LATENCY_LIMIT,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("ondemand"),
|
||||
.kobj_type = { .default_attrs = od_attributes },
|
||||
.gov_dbs_timer = od_dbs_timer,
|
||||
.alloc = od_alloc,
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
struct od_policy_dbs_info {
|
||||
struct policy_dbs_info policy_dbs;
|
||||
struct cpufreq_frequency_table *freq_table;
|
||||
unsigned int freq_lo;
|
||||
unsigned int freq_lo_delay_us;
|
||||
unsigned int freq_hi_delay_us;
|
||||
|
||||
@@ -16,27 +16,16 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
static int cpufreq_governor_performance(struct cpufreq_policy *policy,
|
||||
unsigned int event)
|
||||
static void cpufreq_gov_performance_limits(struct cpufreq_policy *policy)
|
||||
{
|
||||
switch (event) {
|
||||
case CPUFREQ_GOV_START:
|
||||
case CPUFREQ_GOV_LIMITS:
|
||||
pr_debug("setting to %u kHz because of event %u\n",
|
||||
policy->max, event);
|
||||
__cpufreq_driver_target(policy, policy->max,
|
||||
CPUFREQ_RELATION_H);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
pr_debug("setting to %u kHz\n", policy->max);
|
||||
__cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
|
||||
}
|
||||
|
||||
static struct cpufreq_governor cpufreq_gov_performance = {
|
||||
.name = "performance",
|
||||
.governor = cpufreq_governor_performance,
|
||||
.owner = THIS_MODULE,
|
||||
.limits = cpufreq_gov_performance_limits,
|
||||
};
|
||||
|
||||
static int __init cpufreq_gov_performance_init(void)
|
||||
|
||||
@@ -16,26 +16,15 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
|
||||
unsigned int event)
|
||||
static void cpufreq_gov_powersave_limits(struct cpufreq_policy *policy)
|
||||
{
|
||||
switch (event) {
|
||||
case CPUFREQ_GOV_START:
|
||||
case CPUFREQ_GOV_LIMITS:
|
||||
pr_debug("setting to %u kHz because of event %u\n",
|
||||
policy->min, event);
|
||||
__cpufreq_driver_target(policy, policy->min,
|
||||
CPUFREQ_RELATION_L);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
pr_debug("setting to %u kHz\n", policy->min);
|
||||
__cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
|
||||
}
|
||||
|
||||
static struct cpufreq_governor cpufreq_gov_powersave = {
|
||||
.name = "powersave",
|
||||
.governor = cpufreq_governor_powersave,
|
||||
.limits = cpufreq_gov_powersave_limits,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
+22
-135
@@ -15,7 +15,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/cputime.h>
|
||||
|
||||
static spinlock_t cpufreq_stats_lock;
|
||||
static DEFINE_SPINLOCK(cpufreq_stats_lock);
|
||||
|
||||
struct cpufreq_stats {
|
||||
unsigned int total_trans;
|
||||
@@ -52,6 +52,9 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf)
|
||||
ssize_t len = 0;
|
||||
int i;
|
||||
|
||||
if (policy->fast_switch_enabled)
|
||||
return 0;
|
||||
|
||||
cpufreq_stats_update(stats);
|
||||
for (i = 0; i < stats->state_num; i++) {
|
||||
len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i],
|
||||
@@ -68,6 +71,9 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
|
||||
ssize_t len = 0;
|
||||
int i, j;
|
||||
|
||||
if (policy->fast_switch_enabled)
|
||||
return 0;
|
||||
|
||||
len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
|
||||
len += snprintf(buf + len, PAGE_SIZE - len, " : ");
|
||||
for (i = 0; i < stats->state_num; i++) {
|
||||
@@ -130,7 +136,7 @@ static int freq_table_get_index(struct cpufreq_stats *stats, unsigned int freq)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void __cpufreq_stats_free_table(struct cpufreq_policy *policy)
|
||||
void cpufreq_stats_free_table(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cpufreq_stats *stats = policy->stats;
|
||||
|
||||
@@ -146,39 +152,25 @@ static void __cpufreq_stats_free_table(struct cpufreq_policy *policy)
|
||||
policy->stats = NULL;
|
||||
}
|
||||
|
||||
static void cpufreq_stats_free_table(unsigned int cpu)
|
||||
{
|
||||
struct cpufreq_policy *policy;
|
||||
|
||||
policy = cpufreq_cpu_get(cpu);
|
||||
if (!policy)
|
||||
return;
|
||||
|
||||
__cpufreq_stats_free_table(policy);
|
||||
|
||||
cpufreq_cpu_put(policy);
|
||||
}
|
||||
|
||||
static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
|
||||
void cpufreq_stats_create_table(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned int i = 0, count = 0, ret = -ENOMEM;
|
||||
struct cpufreq_stats *stats;
|
||||
unsigned int alloc_size;
|
||||
unsigned int cpu = policy->cpu;
|
||||
struct cpufreq_frequency_table *pos, *table;
|
||||
|
||||
/* We need cpufreq table for creating stats table */
|
||||
table = cpufreq_frequency_get_table(cpu);
|
||||
table = policy->freq_table;
|
||||
if (unlikely(!table))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
/* stats already initialized */
|
||||
if (policy->stats)
|
||||
return -EEXIST;
|
||||
return;
|
||||
|
||||
stats = kzalloc(sizeof(*stats), GFP_KERNEL);
|
||||
if (!stats)
|
||||
return -ENOMEM;
|
||||
return;
|
||||
|
||||
/* Find total allocation size */
|
||||
cpufreq_for_each_valid_entry(pos, table)
|
||||
@@ -215,80 +207,32 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
|
||||
policy->stats = stats;
|
||||
ret = sysfs_create_group(&policy->kobj, &stats_attr_group);
|
||||
if (!ret)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
/* We failed, release resources */
|
||||
policy->stats = NULL;
|
||||
kfree(stats->time_in_state);
|
||||
free_stat:
|
||||
kfree(stats);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cpufreq_stats_create_table(unsigned int cpu)
|
||||
void cpufreq_stats_record_transition(struct cpufreq_policy *policy,
|
||||
unsigned int new_freq)
|
||||
{
|
||||
struct cpufreq_policy *policy;
|
||||
|
||||
/*
|
||||
* "likely(!policy)" because normally cpufreq_stats will be registered
|
||||
* before cpufreq driver
|
||||
*/
|
||||
policy = cpufreq_cpu_get(cpu);
|
||||
if (likely(!policy))
|
||||
return;
|
||||
|
||||
__cpufreq_stats_create_table(policy);
|
||||
|
||||
cpufreq_cpu_put(policy);
|
||||
}
|
||||
|
||||
static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
|
||||
unsigned long val, void *data)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cpufreq_policy *policy = data;
|
||||
|
||||
if (val == CPUFREQ_CREATE_POLICY)
|
||||
ret = __cpufreq_stats_create_table(policy);
|
||||
else if (val == CPUFREQ_REMOVE_POLICY)
|
||||
__cpufreq_stats_free_table(policy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
|
||||
unsigned long val, void *data)
|
||||
{
|
||||
struct cpufreq_freqs *freq = data;
|
||||
struct cpufreq_policy *policy = cpufreq_cpu_get(freq->cpu);
|
||||
struct cpufreq_stats *stats;
|
||||
struct cpufreq_stats *stats = policy->stats;
|
||||
int old_index, new_index;
|
||||
|
||||
if (!policy) {
|
||||
pr_err("%s: No policy found\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (val != CPUFREQ_POSTCHANGE)
|
||||
goto put_policy;
|
||||
|
||||
if (!policy->stats) {
|
||||
if (!stats) {
|
||||
pr_debug("%s: No stats found\n", __func__);
|
||||
goto put_policy;
|
||||
return;
|
||||
}
|
||||
|
||||
stats = policy->stats;
|
||||
|
||||
old_index = stats->last_index;
|
||||
new_index = freq_table_get_index(stats, freq->new);
|
||||
new_index = freq_table_get_index(stats, new_freq);
|
||||
|
||||
/* We can't do stats->time_in_state[-1]= .. */
|
||||
if (old_index == -1 || new_index == -1)
|
||||
goto put_policy;
|
||||
|
||||
if (old_index == new_index)
|
||||
goto put_policy;
|
||||
if (old_index == -1 || new_index == -1 || old_index == new_index)
|
||||
return;
|
||||
|
||||
cpufreq_stats_update(stats);
|
||||
|
||||
@@ -297,61 +241,4 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
|
||||
stats->trans_table[old_index * stats->max_state + new_index]++;
|
||||
#endif
|
||||
stats->total_trans++;
|
||||
|
||||
put_policy:
|
||||
cpufreq_cpu_put(policy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block notifier_policy_block = {
|
||||
.notifier_call = cpufreq_stat_notifier_policy
|
||||
};
|
||||
|
||||
static struct notifier_block notifier_trans_block = {
|
||||
.notifier_call = cpufreq_stat_notifier_trans
|
||||
};
|
||||
|
||||
static int __init cpufreq_stats_init(void)
|
||||
{
|
||||
int ret;
|
||||
unsigned int cpu;
|
||||
|
||||
spin_lock_init(&cpufreq_stats_lock);
|
||||
ret = cpufreq_register_notifier(¬ifier_policy_block,
|
||||
CPUFREQ_POLICY_NOTIFIER);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for_each_online_cpu(cpu)
|
||||
cpufreq_stats_create_table(cpu);
|
||||
|
||||
ret = cpufreq_register_notifier(¬ifier_trans_block,
|
||||
CPUFREQ_TRANSITION_NOTIFIER);
|
||||
if (ret) {
|
||||
cpufreq_unregister_notifier(¬ifier_policy_block,
|
||||
CPUFREQ_POLICY_NOTIFIER);
|
||||
for_each_online_cpu(cpu)
|
||||
cpufreq_stats_free_table(cpu);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static void __exit cpufreq_stats_exit(void)
|
||||
{
|
||||
unsigned int cpu;
|
||||
|
||||
cpufreq_unregister_notifier(¬ifier_policy_block,
|
||||
CPUFREQ_POLICY_NOTIFIER);
|
||||
cpufreq_unregister_notifier(¬ifier_trans_block,
|
||||
CPUFREQ_TRANSITION_NOTIFIER);
|
||||
for_each_online_cpu(cpu)
|
||||
cpufreq_stats_free_table(cpu);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Zou Nan hai <nanhai.zou@intel.com>");
|
||||
MODULE_DESCRIPTION("Export cpufreq stats via sysfs");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(cpufreq_stats_init);
|
||||
module_exit(cpufreq_stats_exit);
|
||||
|
||||
@@ -65,66 +65,66 @@ static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
|
||||
unsigned int event)
|
||||
static void cpufreq_userspace_policy_exit(struct cpufreq_policy *policy)
|
||||
{
|
||||
mutex_lock(&userspace_mutex);
|
||||
kfree(policy->governor_data);
|
||||
policy->governor_data = NULL;
|
||||
mutex_unlock(&userspace_mutex);
|
||||
}
|
||||
|
||||
static int cpufreq_userspace_policy_start(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned int *setspeed = policy->governor_data;
|
||||
unsigned int cpu = policy->cpu;
|
||||
int rc = 0;
|
||||
|
||||
if (event == CPUFREQ_GOV_POLICY_INIT)
|
||||
return cpufreq_userspace_policy_init(policy);
|
||||
BUG_ON(!policy->cur);
|
||||
pr_debug("started managing cpu %u\n", policy->cpu);
|
||||
|
||||
if (!setspeed)
|
||||
return -EINVAL;
|
||||
mutex_lock(&userspace_mutex);
|
||||
per_cpu(cpu_is_managed, policy->cpu) = 1;
|
||||
*setspeed = policy->cur;
|
||||
mutex_unlock(&userspace_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case CPUFREQ_GOV_POLICY_EXIT:
|
||||
mutex_lock(&userspace_mutex);
|
||||
policy->governor_data = NULL;
|
||||
kfree(setspeed);
|
||||
mutex_unlock(&userspace_mutex);
|
||||
break;
|
||||
case CPUFREQ_GOV_START:
|
||||
BUG_ON(!policy->cur);
|
||||
pr_debug("started managing cpu %u\n", cpu);
|
||||
static void cpufreq_userspace_policy_stop(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned int *setspeed = policy->governor_data;
|
||||
|
||||
mutex_lock(&userspace_mutex);
|
||||
per_cpu(cpu_is_managed, cpu) = 1;
|
||||
*setspeed = policy->cur;
|
||||
mutex_unlock(&userspace_mutex);
|
||||
break;
|
||||
case CPUFREQ_GOV_STOP:
|
||||
pr_debug("managing cpu %u stopped\n", cpu);
|
||||
pr_debug("managing cpu %u stopped\n", policy->cpu);
|
||||
|
||||
mutex_lock(&userspace_mutex);
|
||||
per_cpu(cpu_is_managed, cpu) = 0;
|
||||
*setspeed = 0;
|
||||
mutex_unlock(&userspace_mutex);
|
||||
break;
|
||||
case CPUFREQ_GOV_LIMITS:
|
||||
mutex_lock(&userspace_mutex);
|
||||
pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n",
|
||||
cpu, policy->min, policy->max, policy->cur, *setspeed);
|
||||
mutex_lock(&userspace_mutex);
|
||||
per_cpu(cpu_is_managed, policy->cpu) = 0;
|
||||
*setspeed = 0;
|
||||
mutex_unlock(&userspace_mutex);
|
||||
}
|
||||
|
||||
if (policy->max < *setspeed)
|
||||
__cpufreq_driver_target(policy, policy->max,
|
||||
CPUFREQ_RELATION_H);
|
||||
else if (policy->min > *setspeed)
|
||||
__cpufreq_driver_target(policy, policy->min,
|
||||
CPUFREQ_RELATION_L);
|
||||
else
|
||||
__cpufreq_driver_target(policy, *setspeed,
|
||||
CPUFREQ_RELATION_L);
|
||||
mutex_unlock(&userspace_mutex);
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
static void cpufreq_userspace_policy_limits(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned int *setspeed = policy->governor_data;
|
||||
|
||||
mutex_lock(&userspace_mutex);
|
||||
|
||||
pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n",
|
||||
policy->cpu, policy->min, policy->max, policy->cur, *setspeed);
|
||||
|
||||
if (policy->max < *setspeed)
|
||||
__cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
|
||||
else if (policy->min > *setspeed)
|
||||
__cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
|
||||
else
|
||||
__cpufreq_driver_target(policy, *setspeed, CPUFREQ_RELATION_L);
|
||||
|
||||
mutex_unlock(&userspace_mutex);
|
||||
}
|
||||
|
||||
static struct cpufreq_governor cpufreq_gov_userspace = {
|
||||
.name = "userspace",
|
||||
.governor = cpufreq_governor_userspace,
|
||||
.init = cpufreq_userspace_policy_init,
|
||||
.exit = cpufreq_userspace_policy_exit,
|
||||
.start = cpufreq_userspace_policy_start,
|
||||
.stop = cpufreq_userspace_policy_stop,
|
||||
.limits = cpufreq_userspace_policy_limits,
|
||||
.store_setspeed = cpufreq_set,
|
||||
.show_setspeed = show_speed,
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
@@ -38,26 +38,6 @@ struct davinci_cpufreq {
|
||||
};
|
||||
static struct davinci_cpufreq cpufreq;
|
||||
|
||||
static int davinci_verify_speed(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
|
||||
struct cpufreq_frequency_table *freq_table = pdata->freq_table;
|
||||
struct clk *armclk = cpufreq.armclk;
|
||||
|
||||
if (freq_table)
|
||||
return cpufreq_frequency_table_verify(policy, freq_table);
|
||||
|
||||
if (policy->cpu)
|
||||
return -EINVAL;
|
||||
|
||||
cpufreq_verify_within_cpu_limits(policy);
|
||||
policy->min = clk_round_rate(armclk, policy->min * 1000) / 1000;
|
||||
policy->max = clk_round_rate(armclk, policy->max * 1000) / 1000;
|
||||
cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
policy->cpuinfo.max_freq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int davinci_target(struct cpufreq_policy *policy, unsigned int idx)
|
||||
{
|
||||
struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
|
||||
@@ -121,7 +101,7 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
static struct cpufreq_driver davinci_driver = {
|
||||
.flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
|
||||
.verify = davinci_verify_speed,
|
||||
.verify = cpufreq_generic_frequency_table_verify,
|
||||
.target_index = davinci_target,
|
||||
.get = cpufreq_generic_get,
|
||||
.init = davinci_cpu_init,
|
||||
|
||||
@@ -63,8 +63,6 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
|
||||
|
||||
|
||||
int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
|
||||
struct cpufreq_frequency_table *table)
|
||||
@@ -108,20 +106,16 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
|
||||
*/
|
||||
int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cpufreq_frequency_table *table =
|
||||
cpufreq_frequency_get_table(policy->cpu);
|
||||
if (!table)
|
||||
if (!policy->freq_table)
|
||||
return -ENODEV;
|
||||
|
||||
return cpufreq_frequency_table_verify(policy, table);
|
||||
return cpufreq_frequency_table_verify(policy, policy->freq_table);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify);
|
||||
|
||||
int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
||||
struct cpufreq_frequency_table *table,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation,
|
||||
unsigned int *index)
|
||||
int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
struct cpufreq_frequency_table optimal = {
|
||||
.driver_data = ~0,
|
||||
@@ -132,7 +126,9 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
||||
.frequency = 0,
|
||||
};
|
||||
struct cpufreq_frequency_table *pos;
|
||||
struct cpufreq_frequency_table *table = policy->freq_table;
|
||||
unsigned int freq, diff, i = 0;
|
||||
int index;
|
||||
|
||||
pr_debug("request for target %u kHz (relation: %u) for cpu %u\n",
|
||||
target_freq, relation, policy->cpu);
|
||||
@@ -196,25 +192,26 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
||||
}
|
||||
}
|
||||
if (optimal.driver_data > i) {
|
||||
if (suboptimal.driver_data > i)
|
||||
return -EINVAL;
|
||||
*index = suboptimal.driver_data;
|
||||
if (suboptimal.driver_data > i) {
|
||||
WARN(1, "Invalid frequency table: %d\n", policy->cpu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
index = suboptimal.driver_data;
|
||||
} else
|
||||
*index = optimal.driver_data;
|
||||
index = optimal.driver_data;
|
||||
|
||||
pr_debug("target index is %u, freq is:%u kHz\n", *index,
|
||||
table[*index].frequency);
|
||||
|
||||
return 0;
|
||||
pr_debug("target index is %u, freq is:%u kHz\n", index,
|
||||
table[index].frequency);
|
||||
return index;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
|
||||
EXPORT_SYMBOL_GPL(cpufreq_table_index_unsorted);
|
||||
|
||||
int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
|
||||
unsigned int freq)
|
||||
{
|
||||
struct cpufreq_frequency_table *pos, *table;
|
||||
struct cpufreq_frequency_table *pos, *table = policy->freq_table;
|
||||
|
||||
table = cpufreq_frequency_get_table(policy->cpu);
|
||||
if (unlikely(!table)) {
|
||||
pr_debug("%s: Unable to find frequency table\n", __func__);
|
||||
return -ENOENT;
|
||||
@@ -300,15 +297,72 @@ struct freq_attr *cpufreq_generic_attr[] = {
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(cpufreq_generic_attr);
|
||||
|
||||
static int set_freq_table_sorted(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cpufreq_frequency_table *pos, *table = policy->freq_table;
|
||||
struct cpufreq_frequency_table *prev = NULL;
|
||||
int ascending = 0;
|
||||
|
||||
policy->freq_table_sorted = CPUFREQ_TABLE_UNSORTED;
|
||||
|
||||
cpufreq_for_each_valid_entry(pos, table) {
|
||||
if (!prev) {
|
||||
prev = pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pos->frequency == prev->frequency) {
|
||||
pr_warn("Duplicate freq-table entries: %u\n",
|
||||
pos->frequency);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Frequency increased from prev to pos */
|
||||
if (pos->frequency > prev->frequency) {
|
||||
/* But frequency was decreasing earlier */
|
||||
if (ascending < 0) {
|
||||
pr_debug("Freq table is unsorted\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ascending++;
|
||||
} else {
|
||||
/* Frequency decreased from prev to pos */
|
||||
|
||||
/* But frequency was increasing earlier */
|
||||
if (ascending > 0) {
|
||||
pr_debug("Freq table is unsorted\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ascending--;
|
||||
}
|
||||
|
||||
prev = pos;
|
||||
}
|
||||
|
||||
if (ascending > 0)
|
||||
policy->freq_table_sorted = CPUFREQ_TABLE_SORTED_ASCENDING;
|
||||
else
|
||||
policy->freq_table_sorted = CPUFREQ_TABLE_SORTED_DESCENDING;
|
||||
|
||||
pr_debug("Freq table is sorted in %s order\n",
|
||||
ascending > 0 ? "ascending" : "descending");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
|
||||
struct cpufreq_frequency_table *table)
|
||||
{
|
||||
int ret = cpufreq_frequency_table_cpuinfo(policy, table);
|
||||
int ret;
|
||||
|
||||
if (!ret)
|
||||
policy->freq_table = table;
|
||||
ret = cpufreq_frequency_table_cpuinfo(policy, table);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
policy->freq_table = table;
|
||||
return set_freq_table_sorted(policy);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
|
||||
|
||||
|
||||
@@ -97,7 +97,6 @@ static inline u64 div_ext_fp(u64 x, u64 y)
|
||||
* read from MPERF MSR between last and current sample
|
||||
* @tsc: Difference of time stamp counter between last and
|
||||
* current sample
|
||||
* @freq: Effective frequency calculated from APERF/MPERF
|
||||
* @time: Current time from scheduler
|
||||
*
|
||||
* This structure is used in the cpudata structure to store performance sample
|
||||
@@ -109,7 +108,6 @@ struct sample {
|
||||
u64 aperf;
|
||||
u64 mperf;
|
||||
u64 tsc;
|
||||
int freq;
|
||||
u64 time;
|
||||
};
|
||||
|
||||
@@ -282,9 +280,9 @@ struct cpu_defaults {
|
||||
static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu);
|
||||
static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu);
|
||||
|
||||
static struct pstate_adjust_policy pid_params;
|
||||
static struct pstate_funcs pstate_funcs;
|
||||
static int hwp_active;
|
||||
static struct pstate_adjust_policy pid_params __read_mostly;
|
||||
static struct pstate_funcs pstate_funcs __read_mostly;
|
||||
static int hwp_active __read_mostly;
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static bool acpi_ppc;
|
||||
@@ -808,7 +806,8 @@ static void __init intel_pstate_sysfs_expose_params(void)
|
||||
static void intel_pstate_hwp_enable(struct cpudata *cpudata)
|
||||
{
|
||||
/* First disable HWP notification interrupt as we don't process them */
|
||||
wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x00);
|
||||
if (static_cpu_has(X86_FEATURE_HWP_NOTIFY))
|
||||
wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x00);
|
||||
|
||||
wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1);
|
||||
}
|
||||
@@ -945,7 +944,7 @@ static int core_get_max_pstate(void)
|
||||
if (err)
|
||||
goto skip_tar;
|
||||
|
||||
tdp_msr = MSR_CONFIG_TDP_NOMINAL + tdp_ctrl;
|
||||
tdp_msr = MSR_CONFIG_TDP_NOMINAL + (tdp_ctrl & 0x3);
|
||||
err = rdmsrl_safe(tdp_msr, &tdp_ratio);
|
||||
if (err)
|
||||
goto skip_tar;
|
||||
@@ -1092,6 +1091,26 @@ static struct cpu_defaults knl_params = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct cpu_defaults bxt_params = {
|
||||
.pid_policy = {
|
||||
.sample_rate_ms = 10,
|
||||
.deadband = 0,
|
||||
.setpoint = 60,
|
||||
.p_gain_pct = 14,
|
||||
.d_gain_pct = 0,
|
||||
.i_gain_pct = 4,
|
||||
},
|
||||
.funcs = {
|
||||
.get_max = core_get_max_pstate,
|
||||
.get_max_physical = core_get_max_pstate_physical,
|
||||
.get_min = core_get_min_pstate,
|
||||
.get_turbo = core_get_turbo_pstate,
|
||||
.get_scaling = core_get_scaling,
|
||||
.get_val = core_get_val,
|
||||
.get_target_pstate = get_target_pstate_use_cpu_load,
|
||||
},
|
||||
};
|
||||
|
||||
static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
|
||||
{
|
||||
int max_perf = cpu->pstate.turbo_pstate;
|
||||
@@ -1114,17 +1133,12 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
|
||||
*min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf);
|
||||
}
|
||||
|
||||
static inline void intel_pstate_record_pstate(struct cpudata *cpu, int pstate)
|
||||
{
|
||||
trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
|
||||
cpu->pstate.current_pstate = pstate;
|
||||
}
|
||||
|
||||
static void intel_pstate_set_min_pstate(struct cpudata *cpu)
|
||||
{
|
||||
int pstate = cpu->pstate.min_pstate;
|
||||
|
||||
intel_pstate_record_pstate(cpu, pstate);
|
||||
trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
|
||||
cpu->pstate.current_pstate = pstate;
|
||||
/*
|
||||
* Generally, there is no guarantee that this code will always run on
|
||||
* the CPU being updated, so force the register update to run on the
|
||||
@@ -1284,10 +1298,11 @@ static inline void intel_pstate_update_pstate(struct cpudata *cpu, int pstate)
|
||||
|
||||
intel_pstate_get_min_max(cpu, &min_perf, &max_perf);
|
||||
pstate = clamp_t(int, pstate, min_perf, max_perf);
|
||||
trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
|
||||
if (pstate == cpu->pstate.current_pstate)
|
||||
return;
|
||||
|
||||
intel_pstate_record_pstate(cpu, pstate);
|
||||
cpu->pstate.current_pstate = pstate;
|
||||
wrmsrl(MSR_IA32_PERF_CTL, pstate_funcs.get_val(cpu, pstate));
|
||||
}
|
||||
|
||||
@@ -1352,11 +1367,12 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
|
||||
ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, core_params),
|
||||
ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_params),
|
||||
ICPU(INTEL_FAM6_XEON_PHI_KNL, knl_params),
|
||||
ICPU(INTEL_FAM6_ATOM_GOLDMONT, bxt_params),
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
|
||||
|
||||
static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] = {
|
||||
static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] __initconst = {
|
||||
ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_params),
|
||||
{}
|
||||
};
|
||||
@@ -1576,12 +1592,12 @@ static struct cpufreq_driver intel_pstate_driver = {
|
||||
.name = "intel_pstate",
|
||||
};
|
||||
|
||||
static int __initdata no_load;
|
||||
static int __initdata no_hwp;
|
||||
static int __initdata hwp_only;
|
||||
static unsigned int force_load;
|
||||
static int no_load __initdata;
|
||||
static int no_hwp __initdata;
|
||||
static int hwp_only __initdata;
|
||||
static unsigned int force_load __initdata;
|
||||
|
||||
static int intel_pstate_msrs_not_valid(void)
|
||||
static int __init intel_pstate_msrs_not_valid(void)
|
||||
{
|
||||
if (!pstate_funcs.get_max() ||
|
||||
!pstate_funcs.get_min() ||
|
||||
@@ -1591,7 +1607,7 @@ static int intel_pstate_msrs_not_valid(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void copy_pid_params(struct pstate_adjust_policy *policy)
|
||||
static void __init copy_pid_params(struct pstate_adjust_policy *policy)
|
||||
{
|
||||
pid_params.sample_rate_ms = policy->sample_rate_ms;
|
||||
pid_params.sample_rate_ns = pid_params.sample_rate_ms * NSEC_PER_MSEC;
|
||||
@@ -1602,7 +1618,7 @@ static void copy_pid_params(struct pstate_adjust_policy *policy)
|
||||
pid_params.setpoint = policy->setpoint;
|
||||
}
|
||||
|
||||
static void copy_cpu_funcs(struct pstate_funcs *funcs)
|
||||
static void __init copy_cpu_funcs(struct pstate_funcs *funcs)
|
||||
{
|
||||
pstate_funcs.get_max = funcs->get_max;
|
||||
pstate_funcs.get_max_physical = funcs->get_max_physical;
|
||||
@@ -1617,7 +1633,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs)
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
|
||||
static bool intel_pstate_no_acpi_pss(void)
|
||||
static bool __init intel_pstate_no_acpi_pss(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1646,7 +1662,7 @@ static bool intel_pstate_no_acpi_pss(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool intel_pstate_has_acpi_ppc(void)
|
||||
static bool __init intel_pstate_has_acpi_ppc(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1674,7 +1690,7 @@ struct hw_vendor_info {
|
||||
};
|
||||
|
||||
/* Hardware vendor-specific info that has its own power management modes */
|
||||
static struct hw_vendor_info vendor_info[] = {
|
||||
static struct hw_vendor_info vendor_info[] __initdata = {
|
||||
{1, "HP ", "ProLiant", PSS},
|
||||
{1, "ORACLE", "X4-2 ", PPC},
|
||||
{1, "ORACLE", "X4-2L ", PPC},
|
||||
@@ -1693,7 +1709,7 @@ static struct hw_vendor_info vendor_info[] = {
|
||||
{0, "", ""},
|
||||
};
|
||||
|
||||
static bool intel_pstate_platform_pwr_mgmt_exists(void)
|
||||
static bool __init intel_pstate_platform_pwr_mgmt_exists(void)
|
||||
{
|
||||
struct acpi_table_header hdr;
|
||||
struct hw_vendor_info *v_info;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user