Commit 9def970e authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

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
  ...
parents 9fedbb3b da7d3abe
...@@ -96,7 +96,7 @@ new - new frequency ...@@ -96,7 +96,7 @@ new - new frequency
For details about OPP, see Documentation/power/opp.txt For details about OPP, see Documentation/power/opp.txt
dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with 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 frequencies that are available for operation. This function provides
a ready to use conversion routine to translate the OPP layer's internal a ready to use conversion routine to translate the OPP layer's internal
information about the available frequencies into a format readily 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 ...@@ -110,7 +110,7 @@ dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with
/* Do things */ /* Do things */
r = dev_pm_opp_init_cpufreq_table(dev, &freq_table); r = dev_pm_opp_init_cpufreq_table(dev, &freq_table);
if (!r) if (!r)
cpufreq_frequency_table_cpuinfo(policy, freq_table); cpufreq_table_validate_and_show(policy, freq_table);
/* Do other things */ /* Do other things */
} }
......
...@@ -231,7 +231,7 @@ if you want to skip one entry in the table, set the frequency to ...@@ -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 CPUFREQ_ENTRY_INVALID. The entries don't need to be in ascending
order. 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); struct cpufreq_frequency_table *table);
the cpuinfo.min_freq and cpuinfo.max_freq values are detected, and 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 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 ...@@ -244,14 +244,12 @@ policy->max, and all other criteria are met. This is helpful for the
->verify call. ->verify call.
int cpufreq_frequency_table_target(struct cpufreq_policy *policy, int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table,
unsigned int target_freq, unsigned int target_freq,
unsigned int relation, unsigned int relation);
unsigned int *index);
is the corresponding frequency table helper for the ->target is the corresponding frequency table helper for the ->target
stage. Just pass the values to this function, and the unsigned int stage. Just pass the values to this function, and this function
index returns the number of the frequency table entry which contains returns the number of the frequency table entry which contains
the frequency the CPU shall be set to. the frequency the CPU shall be set to.
The following macros can be used as iterators over cpufreq_frequency_table: The following macros can be used as iterators over cpufreq_frequency_table:
......
...@@ -159,8 +159,8 @@ to be strictly associated with a P-state. ...@@ -159,8 +159,8 @@ to be strictly associated with a P-state.
2.2 cpuinfo_transition_latency: 2.2 cpuinfo_transition_latency:
------------------------------- -------------------------------
The cpuinfo_transition_latency field is CPUFREQ_ETERNAL. The PCC specification The cpuinfo_transition_latency field is 0. The PCC specification does
does not include a field to expose this value currently. not include a field to expose this value currently.
2.3 cpuinfo_cur_freq: 2.3 cpuinfo_cur_freq:
--------------------- ---------------------
......
...@@ -85,27 +85,21 @@ static void spu_gov_cancel_work(struct spu_gov_info_struct *info) ...@@ -85,27 +85,21 @@ static void spu_gov_cancel_work(struct spu_gov_info_struct *info)
cancel_delayed_work_sync(&info->work); 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; 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 i;
int ret = 0;
info = &per_cpu(spu_gov_info, cpu);
switch (event) {
case CPUFREQ_GOV_START:
if (!cpu_online(cpu)) { if (!cpu_online(cpu)) {
printk(KERN_ERR "cpu %d is not online\n", cpu); printk(KERN_ERR "cpu %d is not online\n", cpu);
ret = -EINVAL; return -EINVAL;
break;
} }
if (!policy->cur) { if (!policy->cur) {
printk(KERN_ERR "no cpu specified in policy\n"); printk(KERN_ERR "no cpu specified in policy\n");
ret = -EINVAL; return -EINVAL;
break;
} }
/* initialize spu_gov_info for all affected cpus */ /* initialize spu_gov_info for all affected cpus */
...@@ -119,9 +113,15 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event) ...@@ -119,9 +113,15 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
/* setup timer */ /* setup timer */
spu_gov_init_work(info); spu_gov_init_work(info);
break; 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;
case CPUFREQ_GOV_STOP:
/* cancel timer */ /* cancel timer */
spu_gov_cancel_work(info); spu_gov_cancel_work(info);
...@@ -130,16 +130,12 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event) ...@@ -130,16 +130,12 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
info = &per_cpu(spu_gov_info, i); info = &per_cpu(spu_gov_info, i);
info->policy = NULL; info->policy = NULL;
} }
break;
}
return ret;
} }
static struct cpufreq_governor spu_governor = { static struct cpufreq_governor spu_governor = {
.name = "spudemand", .name = "spudemand",
.governor = spu_gov_govern, .start = spu_gov_start,
.stop = spu_gov_stop,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -31,23 +31,18 @@ config CPU_FREQ_BOOST_SW ...@@ -31,23 +31,18 @@ config CPU_FREQ_BOOST_SW
depends on THERMAL depends on THERMAL
config CPU_FREQ_STAT config CPU_FREQ_STAT
tristate "CPU frequency translation statistics" bool "CPU frequency transition statistics"
default y default y
help help
This driver exports CPU frequency statistics information through sysfs Export 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.
If in doubt, say N. If in doubt, say N.
config CPU_FREQ_STAT_DETAILS config CPU_FREQ_STAT_DETAILS
bool "CPU frequency translation statistics details" bool "CPU frequency transition statistics details"
depends on CPU_FREQ_STAT depends on CPU_FREQ_STAT
help help
This will show detail CPU frequency translation table in sysfs file Show detailed CPU frequency transition table in sysfs.
system.
If in doubt, say N. If in doubt, say N.
......
...@@ -468,20 +468,17 @@ unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy, ...@@ -468,20 +468,17 @@ unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy,
struct acpi_cpufreq_data *data = policy->driver_data; struct acpi_cpufreq_data *data = policy->driver_data;
struct acpi_processor_performance *perf; struct acpi_processor_performance *perf;
struct cpufreq_frequency_table *entry; 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. * 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; if (policy->cached_target_freq == target_freq)
do { index = policy->cached_resolved_idx;
entry++; else
freq = entry->frequency; index = cpufreq_table_find_index_dl(policy, target_freq);
} while (freq >= target_freq && freq != CPUFREQ_TABLE_END);
entry--; entry = &policy->freq_table[index];
next_freq = entry->frequency; next_freq = entry->frequency;
next_perf_state = entry->driver_data; next_perf_state = entry->driver_data;
......
...@@ -48,9 +48,8 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy, ...@@ -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 policy_dbs_info *policy_dbs = policy->governor_data;
struct dbs_data *od_data = policy_dbs->dbs_data; struct dbs_data *od_data = policy_dbs->dbs_data;
struct od_dbs_tuners *od_tuners = od_data->tuners; 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; return freq_next;
rdmsr_on_cpu(policy->cpu, MSR_AMD64_FREQ_SENSITIVITY_ACTUAL, 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, ...@@ -92,10 +91,9 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy,
else { else {
unsigned int index; unsigned int index;
cpufreq_frequency_table_target(policy, index = cpufreq_table_find_index_h(policy,
od_info->freq_table, policy->cur - 1, policy->cur - 1);
CPUFREQ_RELATION_H, &index); freq_next = policy->freq_table[index].frequency;
freq_next = od_info->freq_table[index].frequency;
} }
data->freq_prev = freq_next; data->freq_prev = freq_next;
......
This diff is collapsed.
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
struct cs_policy_dbs_info { struct cs_policy_dbs_info {
struct policy_dbs_info policy_dbs; struct policy_dbs_info policy_dbs;
unsigned int down_skip; unsigned int down_skip;
unsigned int requested_freq;
}; };
static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs) 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) ...@@ -75,19 +74,17 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
/* Check for frequency increase */ /* Check for frequency increase */
if (load > dbs_data->up_threshold) { if (load > dbs_data->up_threshold) {
unsigned int requested_freq = policy->cur;
dbs_info->down_skip = 0; dbs_info->down_skip = 0;
/* if we are already at full speed then break out early */ /* 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; 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_driver_target(policy, requested_freq, CPUFREQ_RELATION_H);
CPUFREQ_RELATION_H);
goto out; goto out;
} }
...@@ -98,36 +95,27 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy) ...@@ -98,36 +95,27 @@ static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
/* Check for frequency decrease */ /* Check for frequency decrease */
if (load < cs_tuners->down_threshold) { 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 we cannot reduce the frequency anymore, break out early
*/ */
if (policy->cur == policy->min) if (requested_freq == policy->min)
goto out; goto out;
freq_target = get_freq_target(cs_tuners, policy); freq_target = get_freq_target(cs_tuners, policy);
if (dbs_info->requested_freq > freq_target) if (requested_freq > freq_target)
dbs_info->requested_freq -= freq_target; requested_freq -= freq_target;
else else
dbs_info->requested_freq = policy->min; requested_freq = policy->min;
__cpufreq_driver_target(policy, dbs_info->requested_freq, __cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_L);
CPUFREQ_RELATION_L);
} }
out: out:
return dbs_data->sampling_rate; 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 ************************/ /************************** sysfs interface ************************/
static struct dbs_governor cs_dbs_gov;
static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set, static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -268,15 +256,13 @@ static void cs_free(struct policy_dbs_info *policy_dbs) ...@@ -268,15 +256,13 @@ static void cs_free(struct policy_dbs_info *policy_dbs)
kfree(to_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; struct cs_dbs_tuners *tuners;
tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
if (!tuners) { if (!tuners)
pr_err("%s: kzalloc failed\n", __func__);
return -ENOMEM; return -ENOMEM;
}
tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD; tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD;
tuners->freq_step = DEF_FREQUENCY_STEP; tuners->freq_step = DEF_FREQUENCY_STEP;
...@@ -288,19 +274,11 @@ static int cs_init(struct dbs_data *dbs_data, bool notify) ...@@ -288,19 +274,11 @@ static int cs_init(struct dbs_data *dbs_data, bool notify)
dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
jiffies_to_usecs(10); jiffies_to_usecs(10);
if (notify)
cpufreq_register_notifier(&cs_cpufreq_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER);
return 0; 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); kfree(dbs_data->tuners);
} }
...@@ -309,16 +287,10 @@ static void cs_start(struct cpufreq_policy *policy) ...@@ -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); struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
dbs_info->down_skip = 0; dbs_info->down_skip = 0;
dbs_info->requested_freq = policy->cur;
} }
static struct dbs_governor cs_dbs_gov = { static struct dbs_governor cs_governor = {
.gov = { .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
.name = "conservative",
.governor = cpufreq_governor_dbs,
.max_transition_latency = TRANSITION_LATENCY_LIMIT,
.owner = THIS_MODULE,
},
.kobj_type = { .default_attrs = cs_attributes }, .kobj_type = { .default_attrs = cs_attributes },
.gov_dbs_timer = cs_dbs_timer, .gov_dbs_timer = cs_dbs_timer,
.alloc = cs_alloc, .alloc = cs_alloc,
...@@ -328,33 +300,7 @@ static struct dbs_governor cs_dbs_gov = { ...@@ -328,33 +300,7 @@ static struct dbs_governor cs_dbs_gov = {
.start = cs_start, .start = cs_start,
}; };
#define CPU_FREQ_GOV_CONSERVATIVE (&cs_dbs_gov.gov) #define CPU_FREQ_GOV_CONSERVATIVE (&cs_governor.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;
}
static int __init cpufreq_gov_dbs_init(void) static int __init cpufreq_gov_dbs_init(void)
{ {
......
...@@ -336,17 +336,6 @@ static inline void gov_clear_update_util(struct cpufreq_policy *policy) ...@@ -336,17 +336,6 @@ static inline void gov_clear_update_util(struct cpufreq_policy *policy)
synchronize_sched(); 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, static struct policy_dbs_info *alloc_policy_dbs_info(struct cpufreq_policy *policy,
struct dbs_governor *gov) struct dbs_governor *gov)
{ {
...@@ -389,7 +378,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs, ...@@ -389,7 +378,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,
gov->free(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_governor *gov = dbs_governor_of(policy);
struct dbs_data *dbs_data; struct dbs_data *dbs_data;
...@@ -429,7 +418,7 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy) ...@@ -429,7 +418,7 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
gov_attr_set_init(&dbs_data->attr_set, &policy_dbs->list); 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) if (ret)
goto free_policy_dbs_info; goto free_policy_dbs_info;
...@@ -458,13 +447,13 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy) ...@@ -458,13 +447,13 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
goto out; goto out;
/* Failure, so roll back. */ /* 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; policy->governor_data = NULL;
if (!have_governor_per_policy()) if (!have_governor_per_policy())
gov->gdbs_data = NULL; gov->gdbs_data = NULL;
gov->exit(dbs_data, !policy->governor->initialized); gov->exit(dbs_data);
kfree(dbs_data); kfree(dbs_data);
free_policy_dbs_info: free_policy_dbs_info:
...@@ -474,8 +463,9 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy) ...@@ -474,8 +463,9 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
mutex_unlock(&gov_dbs_data_mutex); mutex_unlock(&gov_dbs_data_mutex);
return ret; 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 dbs_governor *gov = dbs_governor_of(policy);
struct policy_dbs_info *policy_dbs = policy->governor_data; struct policy_dbs_info *policy_dbs = policy->governor_data;
...@@ -493,17 +483,17 @@ static int cpufreq_governor_exit(struct cpufreq_policy *policy) ...@@ -493,17 +483,17 @@ static int cpufreq_governor_exit(struct cpufreq_policy *policy)
if (!have_governor_per_policy()) if (!have_governor_per_policy())
gov->gdbs_data = NULL; gov->gdbs_data = NULL;
gov->exit(dbs_data, policy->governor->initialized == 1); gov->exit(dbs_data);
kfree(dbs_data); kfree(dbs_data);
} }
free_policy_dbs_info(policy_dbs, gov); free_policy_dbs_info(policy_dbs, gov);
mutex_unlock(&gov_dbs_data_mutex); 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 dbs_governor *gov = dbs_governor_of(policy);
struct policy_dbs_info *policy_dbs = policy->governor_data; struct policy_dbs_info *policy_dbs = policy->governor_data;
...@@ -539,47 +529,28 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy) ...@@ -539,47 +529,28 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy)
gov_set_update_util(policy_dbs, sampling_rate); gov_set_update_util(policy_dbs, sampling_rate);
return 0; 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); struct policy_dbs_info *policy_dbs = policy->governor_data;
return 0;
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);
static int cpufreq_governor_limits(struct cpufreq_policy *policy) void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy)
{ {
struct policy_dbs_info *policy_dbs = policy->governor_data; struct policy_dbs_info *policy_dbs = policy->governor_data;
mutex_lock(&policy_dbs->timer_mutex); mutex_lock(&policy_dbs->timer_mutex);
cpufreq_policy_apply_limits(policy);
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);
gov_update_sample_delay(policy_dbs, 0); gov_update_sample_delay(policy_dbs, 0);
mutex_unlock(&policy_dbs->timer_mutex); 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 { ...@@ -138,8 +138,8 @@ struct dbs_governor {
unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy); unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy);
struct policy_dbs_info *(*alloc)(void); struct policy_dbs_info *(*alloc)(void);
void (*free)(struct policy_dbs_info *policy_dbs); void (*free)(struct policy_dbs_info *policy_dbs);
int (*init)(struct dbs_data *dbs_data, bool notify); int (*init)(struct dbs_data *dbs_data);
void (*exit)(struct dbs_data *dbs_data, bool notify); void (*exit)(struct dbs_data *dbs_data);
void (*start)(struct cpufreq_policy *policy); void (*start)(struct cpufreq_policy *policy);
}; };
...@@ -148,6 +148,25 @@ static inline struct dbs_governor *dbs_governor_of(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); 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 */ /* Governor specific operations */
struct od_ops { struct od_ops {
unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy, unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
...@@ -155,7 +174,6 @@ struct od_ops { ...@@ -155,7 +174,6 @@ struct od_ops {
}; };
unsigned int dbs_update(struct cpufreq_policy *policy); 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) void od_register_powersave_bias_handler(unsigned int (*f)
(struct cpufreq_policy *, unsigned int, unsigned int), (struct cpufreq_policy *, unsigned int, unsigned int),
unsigned int powersave_bias); unsigned int powersave_bias);
......
...@@ -65,34 +65,30 @@ static unsigned int generic_powersave_bias_target(struct cpufreq_policy *policy, ...@@ -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_req, freq_reduc, freq_avg;
unsigned int freq_hi, freq_lo; unsigned int freq_hi, freq_lo;
unsigned int index = 0; unsigned int index;
unsigned int delay_hi_us; unsigned int delay_hi_us;
struct policy_dbs_info *policy_dbs = policy->governor_data; struct policy_dbs_info *policy_dbs = policy->governor_data;
struct od_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs); struct od_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
struct dbs_data *dbs_data = policy_dbs->dbs_data; struct dbs_data *dbs_data = policy_dbs->dbs_data;
struct od_dbs_tuners *od_tuners = dbs_data->tuners; 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 = 0;
dbs_info->freq_lo_delay_us = 0; dbs_info->freq_lo_delay_us = 0;
return freq_next; return freq_next;
} }
cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next, index = cpufreq_frequency_table_target(policy, freq_next, relation);
relation, &index); freq_req = freq_table[index].frequency;
freq_req = dbs_info->freq_table[index].frequency;
freq_reduc = freq_req * od_tuners->powersave_bias / 1000; freq_reduc = freq_req * od_tuners->powersave_bias / 1000;
freq_avg = freq_req - freq_reduc; freq_avg = freq_req - freq_reduc;
/* Find freq bounds for freq_avg in freq_table */ /* Find freq bounds for freq_avg in freq_table */
index = 0; index = cpufreq_table_find_index_h(policy, freq_avg);
cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, freq_lo = freq_table[index].frequency;
CPUFREQ_RELATION_H, &index); index = cpufreq_table_find_index_l(policy, freq_avg);
freq_lo = dbs_info->freq_table[index].frequency; freq_hi = 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;
/* Find out how long we have to be in hi and lo freqs */ /* Find out how long we have to be in hi and lo freqs */
if (freq_hi == freq_lo) { if (freq_hi == freq_lo) {
...@@ -113,7 +109,6 @@ static void ondemand_powersave_bias_init(struct cpufreq_policy *policy) ...@@ -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); 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; dbs_info->freq_lo = 0;
} }
...@@ -361,17 +356,15 @@ static void od_free(struct policy_dbs_info *policy_dbs) ...@@ -361,17 +356,15 @@ static void od_free(struct policy_dbs_info *policy_dbs)
kfree(to_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; struct od_dbs_tuners *tuners;
u64 idle_time; u64 idle_time;
int cpu; int cpu;
tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
if (!tuners) { if (!tuners)
pr_err("%s: kzalloc failed\n", __func__);
return -ENOMEM; return -ENOMEM;
}
cpu = get_cpu(); cpu = get_cpu();
idle_time = get_cpu_idle_time_us(cpu, NULL); idle_time = get_cpu_idle_time_us(cpu, NULL);
...@@ -402,7 +395,7 @@ static int od_init(struct dbs_data *dbs_data, bool notify) ...@@ -402,7 +395,7 @@ static int od_init(struct dbs_data *dbs_data, bool notify)
return 0; 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); kfree(dbs_data->tuners);
} }
...@@ -420,12 +413,7 @@ static struct od_ops od_ops = { ...@@ -420,12 +413,7 @@ static struct od_ops od_ops = {
}; };
static struct dbs_governor od_dbs_gov = { static struct dbs_governor od_dbs_gov = {
.gov = { .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("ondemand"),
.name = "ondemand",
.governor = cpufreq_governor_dbs,
.max_transition_latency = TRANSITION_LATENCY_LIMIT,
.owner = THIS_MODULE,
},
.kobj_type = { .default_attrs = od_attributes }, .kobj_type = { .default_attrs = od_attributes },
.gov_dbs_timer = od_dbs_timer, .gov_dbs_timer = od_dbs_timer,
.alloc = od_alloc, .alloc = od_alloc,
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
struct od_policy_dbs_info { struct od_policy_dbs_info {
struct policy_dbs_info policy_dbs; struct policy_dbs_info policy_dbs;
struct cpufreq_frequency_table *freq_table;
unsigned int freq_lo; unsigned int freq_lo;
unsigned int freq_lo_delay_us; unsigned int freq_lo_delay_us;
unsigned int freq_hi_delay_us; unsigned int freq_hi_delay_us;
......
...@@ -16,27 +16,16 @@ ...@@ -16,27 +16,16 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
static int cpufreq_governor_performance(struct cpufreq_policy *policy, static void cpufreq_gov_performance_limits(struct cpufreq_policy *policy)
unsigned int event)
{ {
switch (event) { pr_debug("setting to %u kHz\n", policy->max);
case CPUFREQ_GOV_START: __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
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;
} }
static struct cpufreq_governor cpufreq_gov_performance = { static struct cpufreq_governor cpufreq_gov_performance = {
.name = "performance", .name = "performance",
.governor = cpufreq_governor_performance,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.limits = cpufreq_gov_performance_limits,
}; };
static int __init cpufreq_gov_performance_init(void) static int __init cpufreq_gov_performance_init(void)
......
...@@ -16,26 +16,15 @@ ...@@ -16,26 +16,15 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
static int cpufreq_governor_powersave(struct cpufreq_policy *policy, static void cpufreq_gov_powersave_limits(struct cpufreq_policy *policy)
unsigned int event)
{ {
switch (event) { pr_debug("setting to %u kHz\n", policy->min);
case CPUFREQ_GOV_START: __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
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;
} }
static struct cpufreq_governor cpufreq_gov_powersave = { static struct cpufreq_governor cpufreq_gov_powersave = {
.name = "powersave", .name = "powersave",
.governor = cpufreq_governor_powersave, .limits = cpufreq_gov_powersave_limits,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/cputime.h> #include <linux/cputime.h>
static spinlock_t cpufreq_stats_lock; static DEFINE_SPINLOCK(cpufreq_stats_lock);
struct cpufreq_stats { struct cpufreq_stats {
unsigned int total_trans; unsigned int total_trans;
...@@ -52,6 +52,9 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) ...@@ -52,6 +52,9 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf)
ssize_t len = 0; ssize_t len = 0;
int i; int i;
if (policy->fast_switch_enabled)
return 0;
cpufreq_stats_update(stats); cpufreq_stats_update(stats);
for (i = 0; i < stats->state_num; i++) { for (i = 0; i < stats->state_num; i++) {
len += sprintf(buf + len, "%u %llu\n", stats->freq_table[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) ...@@ -68,6 +71,9 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
ssize_t len = 0; ssize_t len = 0;
int i, j; 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, " From : To\n");
len += snprintf(buf + len, PAGE_SIZE - len, " : "); len += snprintf(buf + len, PAGE_SIZE - len, " : ");
for (i = 0; i < stats->state_num; i++) { 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) ...@@ -130,7 +136,7 @@ static int freq_table_get_index(struct cpufreq_stats *stats, unsigned int freq)
return -1; 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; struct cpufreq_stats *stats = policy->stats;
...@@ -146,39 +152,25 @@ static void __cpufreq_stats_free_table(struct cpufreq_policy *policy) ...@@ -146,39 +152,25 @@ static void __cpufreq_stats_free_table(struct cpufreq_policy *policy)
policy->stats = NULL; policy->stats = NULL;
} }
static void cpufreq_stats_free_table(unsigned int cpu) void cpufreq_stats_create_table(struct cpufreq_policy *policy)
{
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)
{ {
unsigned int i = 0, count = 0, ret = -ENOMEM; unsigned int i = 0, count = 0, ret = -ENOMEM;
struct cpufreq_stats *stats; struct cpufreq_stats *stats;
unsigned int alloc_size; unsigned int alloc_size;
unsigned int cpu = policy->cpu;
struct cpufreq_frequency_table *pos, *table; struct cpufreq_frequency_table *pos, *table;
/* We need cpufreq table for creating stats table */ /* We need cpufreq table for creating stats table */
table = cpufreq_frequency_get_table(cpu); table = policy->freq_table;
if (unlikely(!table)) if (unlikely(!table))
return 0; return;
/* stats already initialized */ /* stats already initialized */
if (policy->stats) if (policy->stats)
return -EEXIST; return;
stats = kzalloc(sizeof(*stats), GFP_KERNEL); stats = kzalloc(sizeof(*stats), GFP_KERNEL);
if (!stats) if (!stats)
return -ENOMEM; return;
/* Find total allocation size */ /* Find total allocation size */
cpufreq_for_each_valid_entry(pos, table) cpufreq_for_each_valid_entry(pos, table)
...@@ -215,80 +207,32 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) ...@@ -215,80 +207,32 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
policy->stats = stats; policy->stats = stats;
ret = sysfs_create_group(&policy->kobj, &stats_attr_group); ret = sysfs_create_group(&policy->kobj, &stats_attr_group);
if (!ret) if (!ret)
return 0; return;
/* We failed, release resources */ /* We failed, release resources */
policy->stats = NULL; policy->stats = NULL;
kfree(stats->time_in_state); kfree(stats->time_in_state);
free_stat: free_stat:
kfree(stats); kfree(stats);
return ret;
}
static void cpufreq_stats_create_table(unsigned int cpu)
{
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, void cpufreq_stats_record_transition(struct cpufreq_policy *policy,
unsigned long val, void *data) unsigned int new_freq)
{ {
int ret = 0; struct cpufreq_stats *stats = policy->stats;
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;
int old_index, new_index; int old_index, new_index;
if (!policy) { if (!stats) {
pr_err("%s: No policy found\n", __func__);
return 0;
}
if (val != CPUFREQ_POSTCHANGE)
goto put_policy;
if (!policy->stats) {
pr_debug("%s: No stats found\n", __func__); pr_debug("%s: No stats found\n", __func__);
goto put_policy; return;
} }
stats = policy->stats;
old_index = stats->last_index; 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]= .. */ /* We can't do stats->time_in_state[-1]= .. */
if (old_index == -1 || new_index == -1) if (old_index == -1 || new_index == -1 || old_index == new_index)
goto put_policy; return;
if (old_index == new_index)
goto put_policy;
cpufreq_stats_update(stats); cpufreq_stats_update(stats);
...@@ -297,61 +241,4 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb, ...@@ -297,61 +241,4 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
stats->trans_table[old_index * stats->max_state + new_index]++; stats->trans_table[old_index * stats->max_state + new_index]++;
#endif #endif
stats->total_trans++; 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(&notifier_policy_block,
CPUFREQ_POLICY_NOTIFIER);
if (ret)
return ret;
for_each_online_cpu(cpu)
cpufreq_stats_create_table(cpu);
ret = cpufreq_register_notifier(&notifier_trans_block,
CPUFREQ_TRANSITION_NOTIFIER);
if (ret) {
cpufreq_unregister_notifier(&notifier_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(&notifier_policy_block,
CPUFREQ_POLICY_NOTIFIER);
cpufreq_unregister_notifier(&notifier_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) ...@@ -65,66 +65,66 @@ static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy)
return 0; return 0;
} }
static int cpufreq_governor_userspace(struct cpufreq_policy *policy, static void cpufreq_userspace_policy_exit(struct cpufreq_policy *policy)
unsigned int event)
{ {
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);
if (!setspeed)
return -EINVAL;
switch (event) {
case CPUFREQ_GOV_POLICY_EXIT:
mutex_lock(&userspace_mutex); mutex_lock(&userspace_mutex);
kfree(policy->governor_data);
policy->governor_data = NULL; policy->governor_data = NULL;
kfree(setspeed);
mutex_unlock(&userspace_mutex); mutex_unlock(&userspace_mutex);
break; }
case CPUFREQ_GOV_START:
static int cpufreq_userspace_policy_start(struct cpufreq_policy *policy)
{
unsigned int *setspeed = policy->governor_data;
BUG_ON(!policy->cur); BUG_ON(!policy->cur);
pr_debug("started managing cpu %u\n", cpu); pr_debug("started managing cpu %u\n", policy->cpu);
mutex_lock(&userspace_mutex); mutex_lock(&userspace_mutex);
per_cpu(cpu_is_managed, cpu) = 1; per_cpu(cpu_is_managed, policy->cpu) = 1;
*setspeed = policy->cur; *setspeed = policy->cur;
mutex_unlock(&userspace_mutex); mutex_unlock(&userspace_mutex);
break; return 0;
case CPUFREQ_GOV_STOP: }
pr_debug("managing cpu %u stopped\n", cpu);
static void cpufreq_userspace_policy_stop(struct cpufreq_policy *policy)
{
unsigned int *setspeed = policy->governor_data;
pr_debug("managing cpu %u stopped\n", policy->cpu);
mutex_lock(&userspace_mutex); mutex_lock(&userspace_mutex);
per_cpu(cpu_is_managed, cpu) = 0; per_cpu(cpu_is_managed, policy->cpu) = 0;
*setspeed = 0; *setspeed = 0;
mutex_unlock(&userspace_mutex); mutex_unlock(&userspace_mutex);
break; }
case CPUFREQ_GOV_LIMITS:
static void cpufreq_userspace_policy_limits(struct cpufreq_policy *policy)
{
unsigned int *setspeed = policy->governor_data;
mutex_lock(&userspace_mutex); mutex_lock(&userspace_mutex);
pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n", 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); policy->cpu, policy->min, policy->max, policy->cur, *setspeed);
if (policy->max < *setspeed) if (policy->max < *setspeed)
__cpufreq_driver_target(policy, policy->max, __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
CPUFREQ_RELATION_H);
else if (policy->min > *setspeed) else if (policy->min > *setspeed)
__cpufreq_driver_target(policy, policy->min, __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
CPUFREQ_RELATION_L);
else else
__cpufreq_driver_target(policy, *setspeed, __cpufreq_driver_target(policy, *setspeed, CPUFREQ_RELATION_L);
CPUFREQ_RELATION_L);
mutex_unlock(&userspace_mutex); mutex_unlock(&userspace_mutex);
break;
}
return rc;
} }
static struct cpufreq_governor cpufreq_gov_userspace = { static struct cpufreq_governor cpufreq_gov_userspace = {
.name = "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, .store_setspeed = cpufreq_set,
.show_setspeed = show_speed, .show_setspeed = show_speed,
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -38,26 +38,6 @@ struct davinci_cpufreq { ...@@ -38,26 +38,6 @@ struct davinci_cpufreq {
}; };
static struct davinci_cpufreq 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) static int davinci_target(struct cpufreq_policy *policy, unsigned int idx)
{ {
struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
...@@ -121,7 +101,7 @@ static int davinci_cpu_init(struct cpufreq_policy *policy) ...@@ -121,7 +101,7 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)
static struct cpufreq_driver davinci_driver = { static struct cpufreq_driver davinci_driver = {
.flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
.verify = davinci_verify_speed, .verify = cpufreq_generic_frequency_table_verify,
.target_index = davinci_target, .target_index = davinci_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = davinci_cpu_init, .init = davinci_cpu_init,
......
...@@ -63,8 +63,6 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, ...@@ -63,8 +63,6 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
else else
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table) struct cpufreq_frequency_table *table)
...@@ -108,20 +106,16 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); ...@@ -108,20 +106,16 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
*/ */
int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy) int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
{ {
struct cpufreq_frequency_table *table = if (!policy->freq_table)
cpufreq_frequency_get_table(policy->cpu);
if (!table)
return -ENODEV; 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); EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify);
int cpufreq_frequency_table_target(struct cpufreq_policy *policy, int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table,
unsigned int target_freq, unsigned int target_freq,
unsigned int relation, unsigned int relation)
unsigned int *index)
{ {
struct cpufreq_frequency_table optimal = { struct cpufreq_frequency_table optimal = {
.driver_data = ~0, .driver_data = ~0,
...@@ -132,7 +126,9 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, ...@@ -132,7 +126,9 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
.frequency = 0, .frequency = 0,
}; };
struct cpufreq_frequency_table *pos; struct cpufreq_frequency_table *pos;
struct cpufreq_frequency_table *table = policy->freq_table;
unsigned int freq, diff, i = 0; unsigned int freq, diff, i = 0;
int index;
pr_debug("request for target %u kHz (relation: %u) for cpu %u\n", pr_debug("request for target %u kHz (relation: %u) for cpu %u\n",
target_freq, relation, policy->cpu); target_freq, relation, policy->cpu);
...@@ -196,25 +192,26 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, ...@@ -196,25 +192,26 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
} }
} }
if (optimal.driver_data > i) { if (optimal.driver_data > i) {
if (suboptimal.driver_data > i) if (suboptimal.driver_data > i) {
return -EINVAL; WARN(1, "Invalid frequency table: %d\n", policy->cpu);
*index = suboptimal.driver_data; return 0;
} else }
*index = optimal.driver_data;
pr_debug("target index is %u, freq is:%u kHz\n", *index, index = suboptimal.driver_data;
table[*index].frequency); } else
index = optimal.driver_data;
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, int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
unsigned int freq) 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)) { if (unlikely(!table)) {
pr_debug("%s: Unable to find frequency table\n", __func__); pr_debug("%s: Unable to find frequency table\n", __func__);
return -ENOENT; return -ENOENT;
...@@ -300,15 +297,72 @@ struct freq_attr *cpufreq_generic_attr[] = { ...@@ -300,15 +297,72 @@ struct freq_attr *cpufreq_generic_attr[] = {
}; };
EXPORT_SYMBOL_GPL(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, int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table) 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); EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
......
...@@ -97,7 +97,6 @@ static inline u64 div_ext_fp(u64 x, u64 y) ...@@ -97,7 +97,6 @@ static inline u64 div_ext_fp(u64 x, u64 y)
* read from MPERF MSR between last and current sample * read from MPERF MSR between last and current sample
* @tsc: Difference of time stamp counter between last and * @tsc: Difference of time stamp counter between last and
* current sample * current sample
* @freq: Effective frequency calculated from APERF/MPERF
* @time: Current time from scheduler * @time: Current time from scheduler
* *
* This structure is used in the cpudata structure to store performance sample * This structure is used in the cpudata structure to store performance sample
...@@ -109,7 +108,6 @@ struct sample { ...@@ -109,7 +108,6 @@ struct sample {
u64 aperf; u64 aperf;
u64 mperf; u64 mperf;
u64 tsc; u64 tsc;
int freq;
u64 time; u64 time;
}; };
...@@ -282,9 +280,9 @@ struct cpu_defaults { ...@@ -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_performance(struct cpudata *cpu);
static inline int32_t get_target_pstate_use_cpu_load(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_adjust_policy pid_params __read_mostly;
static struct pstate_funcs pstate_funcs; static struct pstate_funcs pstate_funcs __read_mostly;
static int hwp_active; static int hwp_active __read_mostly;
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static bool acpi_ppc; static bool acpi_ppc;
...@@ -808,6 +806,7 @@ static void __init intel_pstate_sysfs_expose_params(void) ...@@ -808,6 +806,7 @@ static void __init intel_pstate_sysfs_expose_params(void)
static void intel_pstate_hwp_enable(struct cpudata *cpudata) static void intel_pstate_hwp_enable(struct cpudata *cpudata)
{ {
/* First disable HWP notification interrupt as we don't process them */ /* First disable HWP notification interrupt as we don't process them */
if (static_cpu_has(X86_FEATURE_HWP_NOTIFY))
wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x00); wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x00);
wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1); wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1);
...@@ -945,7 +944,7 @@ static int core_get_max_pstate(void) ...@@ -945,7 +944,7 @@ static int core_get_max_pstate(void)
if (err) if (err)
goto skip_tar; 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); err = rdmsrl_safe(tdp_msr, &tdp_ratio);
if (err) if (err)
goto skip_tar; goto skip_tar;
...@@ -1092,6 +1091,26 @@ static struct cpu_defaults knl_params = { ...@@ -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) static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
{ {
int max_perf = cpu->pstate.turbo_pstate; 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) ...@@ -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); *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) static void intel_pstate_set_min_pstate(struct cpudata *cpu)
{ {
int pstate = cpu->pstate.min_pstate; 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 * 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 * 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) ...@@ -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); intel_pstate_get_min_max(cpu, &min_perf, &max_perf);
pstate = clamp_t(int, pstate, 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) if (pstate == cpu->pstate.current_pstate)
return; return;
intel_pstate_record_pstate(cpu, pstate); cpu->pstate.current_pstate = pstate;
wrmsrl(MSR_IA32_PERF_CTL, pstate_funcs.get_val(cpu, 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[] = { ...@@ -1352,11 +1367,12 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, core_params), ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, core_params),
ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_params), ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_params),
ICPU(INTEL_FAM6_XEON_PHI_KNL, knl_params), ICPU(INTEL_FAM6_XEON_PHI_KNL, knl_params),
ICPU(INTEL_FAM6_ATOM_GOLDMONT, bxt_params),
{} {}
}; };
MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); 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), ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_params),
{} {}
}; };
...@@ -1576,12 +1592,12 @@ static struct cpufreq_driver intel_pstate_driver = { ...@@ -1576,12 +1592,12 @@ static struct cpufreq_driver intel_pstate_driver = {
.name = "intel_pstate", .name = "intel_pstate",
}; };
static int __initdata no_load; static int no_load __initdata;
static int __initdata no_hwp; static int no_hwp __initdata;
static int __initdata hwp_only; static int hwp_only __initdata;
static unsigned int force_load; 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() || if (!pstate_funcs.get_max() ||
!pstate_funcs.get_min() || !pstate_funcs.get_min() ||
...@@ -1591,7 +1607,7 @@ static int intel_pstate_msrs_not_valid(void) ...@@ -1591,7 +1607,7 @@ static int intel_pstate_msrs_not_valid(void)
return 0; 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_ms = policy->sample_rate_ms;
pid_params.sample_rate_ns = pid_params.sample_rate_ms * NSEC_PER_MSEC; 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) ...@@ -1602,7 +1618,7 @@ static void copy_pid_params(struct pstate_adjust_policy *policy)
pid_params.setpoint = policy->setpoint; 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 = funcs->get_max;
pstate_funcs.get_max_physical = funcs->get_max_physical; pstate_funcs.get_max_physical = funcs->get_max_physical;
...@@ -1617,7 +1633,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs) ...@@ -1617,7 +1633,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs)
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static bool intel_pstate_no_acpi_pss(void) static bool __init intel_pstate_no_acpi_pss(void)
{ {
int i; int i;
...@@ -1646,7 +1662,7 @@ static bool intel_pstate_no_acpi_pss(void) ...@@ -1646,7 +1662,7 @@ static bool intel_pstate_no_acpi_pss(void)
return true; return true;
} }
static bool intel_pstate_has_acpi_ppc(void) static bool __init intel_pstate_has_acpi_ppc(void)
{ {
int i; int i;
...@@ -1674,7 +1690,7 @@ struct hw_vendor_info { ...@@ -1674,7 +1690,7 @@ struct hw_vendor_info {
}; };
/* Hardware vendor-specific info that has its own power management modes */ /* 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, "HP ", "ProLiant", PSS},
{1, "ORACLE", "X4-2 ", PPC}, {1, "ORACLE", "X4-2 ", PPC},
{1, "ORACLE", "X4-2L ", PPC}, {1, "ORACLE", "X4-2L ", PPC},
...@@ -1693,7 +1709,7 @@ static struct hw_vendor_info vendor_info[] = { ...@@ -1693,7 +1709,7 @@ static struct hw_vendor_info vendor_info[] = {
{0, "", ""}, {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 acpi_table_header hdr;
struct hw_vendor_info *v_info; struct hw_vendor_info *v_info;
......
...@@ -70,7 +70,7 @@ static int __init armada_xp_pmsu_cpufreq_init(void) ...@@ -70,7 +70,7 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
continue; continue;
} }
clk = clk_get(cpu_dev, 0); clk = clk_get(cpu_dev, NULL);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
pr_err("Cannot get clock for CPU %d\n", cpu); pr_err("Cannot get clock for CPU %d\n", cpu);
return PTR_ERR(clk); return PTR_ERR(clk);
......
...@@ -555,8 +555,6 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -555,8 +555,6 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->min = policy->cpuinfo.min_freq = policy->min = policy->cpuinfo.min_freq =
ioread32(&pcch_hdr->minimum_frequency) * 1000; ioread32(&pcch_hdr->minimum_frequency) * 1000;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
pr_debug("init: policy->max is %d, policy->min is %d\n", pr_debug("init: policy->max is %d, policy->min is %d\n",
policy->max, policy->min); policy->max, policy->min);
out: out:
......
This diff is collapsed.
...@@ -94,7 +94,7 @@ static int pmi_notifier(struct notifier_block *nb, ...@@ -94,7 +94,7 @@ static int pmi_notifier(struct notifier_block *nb,
unsigned long event, void *data) unsigned long event, void *data)
{ {
struct cpufreq_policy *policy = data; struct cpufreq_policy *policy = data;
struct cpufreq_frequency_table *cbe_freqs; struct cpufreq_frequency_table *cbe_freqs = policy->freq_table;
u8 node; u8 node;
/* Should this really be called for CPUFREQ_ADJUST and CPUFREQ_NOTIFY /* Should this really be called for CPUFREQ_ADJUST and CPUFREQ_NOTIFY
...@@ -103,7 +103,6 @@ static int pmi_notifier(struct notifier_block *nb, ...@@ -103,7 +103,6 @@ static int pmi_notifier(struct notifier_block *nb,
if (event == CPUFREQ_START) if (event == CPUFREQ_START)
return 0; return 0;
cbe_freqs = cpufreq_frequency_get_table(policy->cpu);
node = cbe_cpu_to_node(policy->cpu); node = cbe_cpu_to_node(policy->cpu);
pr_debug("got notified, event=%lu, node=%u\n", event, node); pr_debug("got notified, event=%lu, node=%u\n", event, node);
......
...@@ -293,12 +293,8 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy, ...@@ -293,12 +293,8 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy,
__func__, policy, target_freq, relation); __func__, policy, target_freq, relation);
if (ftab) { if (ftab) {
if (cpufreq_frequency_table_target(policy, ftab, index = cpufreq_frequency_table_target(policy, target_freq,
target_freq, relation, relation);
&index)) {
s3c_freq_dbg("%s: table failed\n", __func__);
return -EINVAL;
}
s3c_freq_dbg("%s: adjust %d to entry %d (%u)\n", __func__, s3c_freq_dbg("%s: adjust %d to entry %d (%u)\n", __func__,
target_freq, index, ftab[index].frequency); target_freq, index, ftab[index].frequency);
...@@ -315,7 +311,6 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy, ...@@ -315,7 +311,6 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy,
pll = NULL; pll = NULL;
} else { } else {
struct cpufreq_policy tmp_policy; struct cpufreq_policy tmp_policy;
int ret;
/* we keep the cpu pll table in Hz, to ensure we get an /* we keep the cpu pll table in Hz, to ensure we get an
* accurate value for the PLL output. */ * accurate value for the PLL output. */
...@@ -323,20 +318,14 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy, ...@@ -323,20 +318,14 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy,
tmp_policy.min = policy->min * 1000; tmp_policy.min = policy->min * 1000;
tmp_policy.max = policy->max * 1000; tmp_policy.max = policy->max * 1000;
tmp_policy.cpu = policy->cpu; tmp_policy.cpu = policy->cpu;
tmp_policy.freq_table = pll_reg;
/* cpufreq_frequency_table_target uses a pointer to 'index' /* cpufreq_frequency_table_target returns the index
* which is the number of the table entry, not the value of * of the table entry, not the value of
* the table entry's index field. */ * the table entry's index field. */
ret = cpufreq_frequency_table_target(&tmp_policy, pll_reg, index = cpufreq_frequency_table_target(&tmp_policy, target_freq,
target_freq, relation, relation);
&index);
if (ret < 0) {
pr_err("%s: no PLL available\n", __func__);
goto err_notpossible;
}
pll = pll_reg + index; pll = pll_reg + index;
s3c_freq_dbg("%s: target %u => %u\n", s3c_freq_dbg("%s: target %u => %u\n",
...@@ -346,10 +335,6 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy, ...@@ -346,10 +335,6 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy,
} }
return s3c_cpufreq_settarget(policy, target_freq, pll); return s3c_cpufreq_settarget(policy, target_freq, pll);
err_notpossible:
pr_err("no compatible settings for %d\n", target_freq);
return -EINVAL;
} }
struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name) struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name)
...@@ -571,11 +556,7 @@ static int s3c_cpufreq_build_freq(void) ...@@ -571,11 +556,7 @@ static int s3c_cpufreq_build_freq(void)
{ {
int size, ret; int size, ret;
if (!cpu_cur.info->calc_freqtable)
return -EINVAL;
kfree(ftab); kfree(ftab);
ftab = NULL;
size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0); size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0);
size++; size++;
......
...@@ -246,12 +246,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) ...@@ -246,12 +246,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
new_freq = s5pv210_freq_table[index].frequency; new_freq = s5pv210_freq_table[index].frequency;
/* Finding current running level index */ /* Finding current running level index */
if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, priv_index = cpufreq_table_find_index_h(policy, old_freq);
old_freq, CPUFREQ_RELATION_H,
&priv_index)) {
ret = -EINVAL;
goto exit;
}
arm_volt = dvs_conf[index].arm_volt; arm_volt = dvs_conf[index].arm_volt;
int_volt = dvs_conf[index].int_volt; int_volt = dvs_conf[index].int_volt;
......
...@@ -787,22 +787,34 @@ __cpufreq_cooling_register(struct device_node *np, ...@@ -787,22 +787,34 @@ __cpufreq_cooling_register(struct device_node *np,
const struct cpumask *clip_cpus, u32 capacitance, const struct cpumask *clip_cpus, u32 capacitance,
get_static_t plat_static_func) get_static_t plat_static_func)
{ {
struct cpufreq_policy *policy;
struct thermal_cooling_device *cool_dev; struct thermal_cooling_device *cool_dev;
struct cpufreq_cooling_device *cpufreq_dev; struct cpufreq_cooling_device *cpufreq_dev;
char dev_name[THERMAL_NAME_LENGTH]; char dev_name[THERMAL_NAME_LENGTH];
struct cpufreq_frequency_table *pos, *table; struct cpufreq_frequency_table *pos, *table;
struct cpumask temp_mask;
unsigned int freq, i, num_cpus; unsigned int freq, i, num_cpus;
int ret; int ret;
table = cpufreq_frequency_get_table(cpumask_first(clip_cpus)); cpumask_and(&temp_mask, clip_cpus, cpu_online_mask);
policy = cpufreq_cpu_get(cpumask_first(&temp_mask));
if (!policy) {
pr_debug("%s: CPUFreq policy not found\n", __func__);
return ERR_PTR(-EPROBE_DEFER);
}
table = policy->freq_table;
if (!table) { if (!table) {
pr_debug("%s: CPUFreq table not found\n", __func__); pr_debug("%s: CPUFreq table not found\n", __func__);
return ERR_PTR(-EPROBE_DEFER); cool_dev = ERR_PTR(-ENODEV);
goto put_policy;
} }
cpufreq_dev = kzalloc(sizeof(*cpufreq_dev), GFP_KERNEL); cpufreq_dev = kzalloc(sizeof(*cpufreq_dev), GFP_KERNEL);
if (!cpufreq_dev) if (!cpufreq_dev) {
return ERR_PTR(-ENOMEM); cool_dev = ERR_PTR(-ENOMEM);
goto put_policy;
}
num_cpus = cpumask_weight(clip_cpus); num_cpus = cpumask_weight(clip_cpus);
cpufreq_dev->time_in_idle = kcalloc(num_cpus, cpufreq_dev->time_in_idle = kcalloc(num_cpus,
...@@ -892,7 +904,7 @@ __cpufreq_cooling_register(struct device_node *np, ...@@ -892,7 +904,7 @@ __cpufreq_cooling_register(struct device_node *np,
CPUFREQ_POLICY_NOTIFIER); CPUFREQ_POLICY_NOTIFIER);
mutex_unlock(&cooling_cpufreq_lock); mutex_unlock(&cooling_cpufreq_lock);
return cool_dev; goto put_policy;
remove_idr: remove_idr:
release_idr(&cpufreq_idr, cpufreq_dev->id); release_idr(&cpufreq_idr, cpufreq_dev->id);
...@@ -906,6 +918,8 @@ __cpufreq_cooling_register(struct device_node *np, ...@@ -906,6 +918,8 @@ __cpufreq_cooling_register(struct device_node *np,
kfree(cpufreq_dev->time_in_idle); kfree(cpufreq_dev->time_in_idle);
free_cdev: free_cdev:
kfree(cpufreq_dev); kfree(cpufreq_dev);
put_policy:
cpufreq_cpu_put(policy);
return cool_dev; return cool_dev;
} }
......
This diff is collapsed.
...@@ -47,6 +47,8 @@ struct sugov_cpu { ...@@ -47,6 +47,8 @@ struct sugov_cpu {
struct update_util_data update_util; struct update_util_data update_util;
struct sugov_policy *sg_policy; struct sugov_policy *sg_policy;
unsigned int cached_raw_freq;
/* The fields below are only needed when sharing a policy. */ /* The fields below are only needed when sharing a policy. */
unsigned long util; unsigned long util;
unsigned long max; unsigned long max;
...@@ -106,7 +108,7 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time, ...@@ -106,7 +108,7 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time,
/** /**
* get_next_freq - Compute a new frequency for a given cpufreq policy. * get_next_freq - Compute a new frequency for a given cpufreq policy.
* @policy: cpufreq policy object to compute the new frequency for. * @sg_cpu: schedutil cpu object to compute the new frequency for.
* @util: Current CPU utilization. * @util: Current CPU utilization.
* @max: CPU capacity. * @max: CPU capacity.
* *
...@@ -121,14 +123,25 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time, ...@@ -121,14 +123,25 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time,
* next_freq = C * curr_freq * util_raw / max * next_freq = C * curr_freq * util_raw / max
* *
* Take C = 1.25 for the frequency tipping point at (util / max) = 0.8. * Take C = 1.25 for the frequency tipping point at (util / max) = 0.8.
*
* The lowest driver-supported frequency which is equal or greater than the raw
* next_freq (as calculated above) is returned, subject to policy min/max and
* cpufreq driver limitations.
*/ */
static unsigned int get_next_freq(struct cpufreq_policy *policy, static unsigned int get_next_freq(struct sugov_cpu *sg_cpu, unsigned long util,
unsigned long util, unsigned long max) unsigned long max)
{ {
struct sugov_policy *sg_policy = sg_cpu->sg_policy;
struct cpufreq_policy *policy = sg_policy->policy;
unsigned int freq = arch_scale_freq_invariant() ? unsigned int freq = arch_scale_freq_invariant() ?
policy->cpuinfo.max_freq : policy->cur; policy->cpuinfo.max_freq : policy->cur;
return (freq + (freq >> 2)) * util / max; freq = (freq + (freq >> 2)) * util / max;
if (freq == sg_cpu->cached_raw_freq && sg_policy->next_freq != UINT_MAX)
return sg_policy->next_freq;
sg_cpu->cached_raw_freq = freq;
return cpufreq_driver_resolve_freq(policy, freq);
} }
static void sugov_update_single(struct update_util_data *hook, u64 time, static void sugov_update_single(struct update_util_data *hook, u64 time,
...@@ -143,13 +156,14 @@ static void sugov_update_single(struct update_util_data *hook, u64 time, ...@@ -143,13 +156,14 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
return; return;
next_f = util == ULONG_MAX ? policy->cpuinfo.max_freq : next_f = util == ULONG_MAX ? policy->cpuinfo.max_freq :
get_next_freq(policy, util, max); get_next_freq(sg_cpu, util, max);
sugov_update_commit(sg_policy, time, next_f); sugov_update_commit(sg_policy, time, next_f);
} }
static unsigned int sugov_next_freq_shared(struct sugov_policy *sg_policy, static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu,
unsigned long util, unsigned long max) unsigned long util, unsigned long max)
{ {
struct sugov_policy *sg_policy = sg_cpu->sg_policy;
struct cpufreq_policy *policy = sg_policy->policy; struct cpufreq_policy *policy = sg_policy->policy;
unsigned int max_f = policy->cpuinfo.max_freq; unsigned int max_f = policy->cpuinfo.max_freq;
u64 last_freq_update_time = sg_policy->last_freq_update_time; u64 last_freq_update_time = sg_policy->last_freq_update_time;
...@@ -189,7 +203,7 @@ static unsigned int sugov_next_freq_shared(struct sugov_policy *sg_policy, ...@@ -189,7 +203,7 @@ static unsigned int sugov_next_freq_shared(struct sugov_policy *sg_policy,
} }
} }
return get_next_freq(policy, util, max); return get_next_freq(sg_cpu, util, max);
} }
static void sugov_update_shared(struct update_util_data *hook, u64 time, static void sugov_update_shared(struct update_util_data *hook, u64 time,
...@@ -206,7 +220,7 @@ static void sugov_update_shared(struct update_util_data *hook, u64 time, ...@@ -206,7 +220,7 @@ static void sugov_update_shared(struct update_util_data *hook, u64 time,
sg_cpu->last_update = time; sg_cpu->last_update = time;
if (sugov_should_update_freq(sg_policy, time)) { if (sugov_should_update_freq(sg_policy, time)) {
next_f = sugov_next_freq_shared(sg_policy, util, max); next_f = sugov_next_freq_shared(sg_cpu, util, max);
sugov_update_commit(sg_policy, time, next_f); sugov_update_commit(sg_policy, time, next_f);
} }
...@@ -394,7 +408,7 @@ static int sugov_init(struct cpufreq_policy *policy) ...@@ -394,7 +408,7 @@ static int sugov_init(struct cpufreq_policy *policy)
return ret; return ret;
} }
static int sugov_exit(struct cpufreq_policy *policy) static void sugov_exit(struct cpufreq_policy *policy)
{ {
struct sugov_policy *sg_policy = policy->governor_data; struct sugov_policy *sg_policy = policy->governor_data;
struct sugov_tunables *tunables = sg_policy->tunables; struct sugov_tunables *tunables = sg_policy->tunables;
...@@ -412,7 +426,6 @@ static int sugov_exit(struct cpufreq_policy *policy) ...@@ -412,7 +426,6 @@ static int sugov_exit(struct cpufreq_policy *policy)
mutex_unlock(&global_tunables_lock); mutex_unlock(&global_tunables_lock);
sugov_policy_free(sg_policy); sugov_policy_free(sg_policy);
return 0;
} }
static int sugov_start(struct cpufreq_policy *policy) static int sugov_start(struct cpufreq_policy *policy)
...@@ -434,6 +447,7 @@ static int sugov_start(struct cpufreq_policy *policy) ...@@ -434,6 +447,7 @@ static int sugov_start(struct cpufreq_policy *policy)
sg_cpu->util = ULONG_MAX; sg_cpu->util = ULONG_MAX;
sg_cpu->max = 0; sg_cpu->max = 0;
sg_cpu->last_update = 0; sg_cpu->last_update = 0;
sg_cpu->cached_raw_freq = 0;
cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util, cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
sugov_update_shared); sugov_update_shared);
} else { } else {
...@@ -444,7 +458,7 @@ static int sugov_start(struct cpufreq_policy *policy) ...@@ -444,7 +458,7 @@ static int sugov_start(struct cpufreq_policy *policy)
return 0; return 0;
} }
static int sugov_stop(struct cpufreq_policy *policy) static void sugov_stop(struct cpufreq_policy *policy)
{ {
struct sugov_policy *sg_policy = policy->governor_data; struct sugov_policy *sg_policy = policy->governor_data;
unsigned int cpu; unsigned int cpu;
...@@ -456,53 +470,29 @@ static int sugov_stop(struct cpufreq_policy *policy) ...@@ -456,53 +470,29 @@ static int sugov_stop(struct cpufreq_policy *policy)
irq_work_sync(&sg_policy->irq_work); irq_work_sync(&sg_policy->irq_work);
cancel_work_sync(&sg_policy->work); cancel_work_sync(&sg_policy->work);
return 0;
} }
static int sugov_limits(struct cpufreq_policy *policy) static void sugov_limits(struct cpufreq_policy *policy)
{ {
struct sugov_policy *sg_policy = policy->governor_data; struct sugov_policy *sg_policy = policy->governor_data;
if (!policy->fast_switch_enabled) { if (!policy->fast_switch_enabled) {
mutex_lock(&sg_policy->work_lock); mutex_lock(&sg_policy->work_lock);
cpufreq_policy_apply_limits(policy);
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);
mutex_unlock(&sg_policy->work_lock); mutex_unlock(&sg_policy->work_lock);
} }
sg_policy->need_freq_update = true; sg_policy->need_freq_update = true;
return 0;
}
int sugov_governor(struct cpufreq_policy *policy, unsigned int event)
{
if (event == CPUFREQ_GOV_POLICY_INIT) {
return sugov_init(policy);
} else if (policy->governor_data) {
switch (event) {
case CPUFREQ_GOV_POLICY_EXIT:
return sugov_exit(policy);
case CPUFREQ_GOV_START:
return sugov_start(policy);
case CPUFREQ_GOV_STOP:
return sugov_stop(policy);
case CPUFREQ_GOV_LIMITS:
return sugov_limits(policy);
}
}
return -EINVAL;
} }
static struct cpufreq_governor schedutil_gov = { static struct cpufreq_governor schedutil_gov = {
.name = "schedutil", .name = "schedutil",
.governor = sugov_governor,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = sugov_init,
.exit = sugov_exit,
.start = sugov_start,
.stop = sugov_stop,
.limits = sugov_limits,
}; };
static int __init sugov_module_init(void) static int __init sugov_module_init(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment