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:
commit
9def970ead
29 changed files with 912 additions and 785 deletions
|
|
@ -36,6 +36,12 @@
|
|||
|
||||
struct cpufreq_governor;
|
||||
|
||||
enum cpufreq_table_sorting {
|
||||
CPUFREQ_TABLE_UNSORTED,
|
||||
CPUFREQ_TABLE_SORTED_ASCENDING,
|
||||
CPUFREQ_TABLE_SORTED_DESCENDING
|
||||
};
|
||||
|
||||
struct cpufreq_freqs {
|
||||
unsigned int cpu; /* cpu nr */
|
||||
unsigned int old;
|
||||
|
|
@ -87,6 +93,7 @@ struct cpufreq_policy {
|
|||
|
||||
struct cpufreq_user_policy user_policy;
|
||||
struct cpufreq_frequency_table *freq_table;
|
||||
enum cpufreq_table_sorting freq_table_sorted;
|
||||
|
||||
struct list_head policy_list;
|
||||
struct kobject kobj;
|
||||
|
|
@ -113,6 +120,10 @@ struct cpufreq_policy {
|
|||
bool fast_switch_possible;
|
||||
bool fast_switch_enabled;
|
||||
|
||||
/* Cached frequency lookup from cpufreq_driver_resolve_freq. */
|
||||
unsigned int cached_target_freq;
|
||||
int cached_resolved_idx;
|
||||
|
||||
/* Synchronization for frequency transitions */
|
||||
bool transition_ongoing; /* Tracks transition status */
|
||||
spinlock_t transition_lock;
|
||||
|
|
@ -185,6 +196,18 @@ static inline unsigned int cpufreq_quick_get_max(unsigned int cpu)
|
|||
static inline void disable_cpufreq(void) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ_STAT
|
||||
void cpufreq_stats_create_table(struct cpufreq_policy *policy);
|
||||
void cpufreq_stats_free_table(struct cpufreq_policy *policy);
|
||||
void cpufreq_stats_record_transition(struct cpufreq_policy *policy,
|
||||
unsigned int new_freq);
|
||||
#else
|
||||
static inline void cpufreq_stats_create_table(struct cpufreq_policy *policy) { }
|
||||
static inline void cpufreq_stats_free_table(struct cpufreq_policy *policy) { }
|
||||
static inline void cpufreq_stats_record_transition(struct cpufreq_policy *policy,
|
||||
unsigned int new_freq) { }
|
||||
#endif /* CONFIG_CPU_FREQ_STAT */
|
||||
|
||||
/*********************************************************************
|
||||
* CPUFREQ DRIVER INTERFACE *
|
||||
*********************************************************************/
|
||||
|
|
@ -251,6 +274,16 @@ struct cpufreq_driver {
|
|||
unsigned int index);
|
||||
unsigned int (*fast_switch)(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq);
|
||||
|
||||
/*
|
||||
* Caches and returns the lowest driver-supported frequency greater than
|
||||
* or equal to the target frequency, subject to any driver limitations.
|
||||
* Does not set the frequency. Only to be implemented for drivers with
|
||||
* target().
|
||||
*/
|
||||
unsigned int (*resolve_freq)(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq);
|
||||
|
||||
/*
|
||||
* Only for drivers with target_index() and CPUFREQ_ASYNC_NOTIFICATION
|
||||
* unset.
|
||||
|
|
@ -455,18 +488,13 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div,
|
|||
#define MIN_LATENCY_MULTIPLIER (20)
|
||||
#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000)
|
||||
|
||||
/* Governor Events */
|
||||
#define CPUFREQ_GOV_START 1
|
||||
#define CPUFREQ_GOV_STOP 2
|
||||
#define CPUFREQ_GOV_LIMITS 3
|
||||
#define CPUFREQ_GOV_POLICY_INIT 4
|
||||
#define CPUFREQ_GOV_POLICY_EXIT 5
|
||||
|
||||
struct cpufreq_governor {
|
||||
char name[CPUFREQ_NAME_LEN];
|
||||
int initialized;
|
||||
int (*governor) (struct cpufreq_policy *policy,
|
||||
unsigned int event);
|
||||
int (*init)(struct cpufreq_policy *policy);
|
||||
void (*exit)(struct cpufreq_policy *policy);
|
||||
int (*start)(struct cpufreq_policy *policy);
|
||||
void (*stop)(struct cpufreq_policy *policy);
|
||||
void (*limits)(struct cpufreq_policy *policy);
|
||||
ssize_t (*show_setspeed) (struct cpufreq_policy *policy,
|
||||
char *buf);
|
||||
int (*store_setspeed) (struct cpufreq_policy *policy,
|
||||
|
|
@ -487,12 +515,22 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
|
|||
int __cpufreq_driver_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation);
|
||||
unsigned int cpufreq_driver_resolve_freq(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq);
|
||||
int cpufreq_register_governor(struct cpufreq_governor *governor);
|
||||
void cpufreq_unregister_governor(struct cpufreq_governor *governor);
|
||||
|
||||
struct cpufreq_governor *cpufreq_default_governor(void);
|
||||
struct cpufreq_governor *cpufreq_fallback_governor(void);
|
||||
|
||||
static inline void cpufreq_policy_apply_limits(struct cpufreq_policy *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);
|
||||
}
|
||||
|
||||
/* Governor attribute set */
|
||||
struct gov_attr_set {
|
||||
struct kobject kobj;
|
||||
|
|
@ -582,11 +620,9 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
|
|||
struct cpufreq_frequency_table *table);
|
||||
int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy);
|
||||
|
||||
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);
|
||||
int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
|
||||
unsigned int freq);
|
||||
|
||||
|
|
@ -597,6 +633,227 @@ int cpufreq_boost_trigger_state(int state);
|
|||
int cpufreq_boost_enabled(void);
|
||||
int cpufreq_enable_boost_support(void);
|
||||
bool policy_has_boost_freq(struct cpufreq_policy *policy);
|
||||
|
||||
/* Find lowest freq at or above target in a table in ascending order */
|
||||
static inline int cpufreq_table_find_index_al(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq)
|
||||
{
|
||||
struct cpufreq_frequency_table *table = policy->freq_table;
|
||||
unsigned int freq;
|
||||
int i, best = -1;
|
||||
|
||||
for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
freq = table[i].frequency;
|
||||
|
||||
if (freq >= target_freq)
|
||||
return i;
|
||||
|
||||
best = i;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/* Find lowest freq at or above target in a table in descending order */
|
||||
static inline int cpufreq_table_find_index_dl(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq)
|
||||
{
|
||||
struct cpufreq_frequency_table *table = policy->freq_table;
|
||||
unsigned int freq;
|
||||
int i, best = -1;
|
||||
|
||||
for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
freq = table[i].frequency;
|
||||
|
||||
if (freq == target_freq)
|
||||
return i;
|
||||
|
||||
if (freq > target_freq) {
|
||||
best = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No freq found above target_freq */
|
||||
if (best == -1)
|
||||
return i;
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/* Works only on sorted freq-tables */
|
||||
static inline int cpufreq_table_find_index_l(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq)
|
||||
{
|
||||
target_freq = clamp_val(target_freq, policy->min, policy->max);
|
||||
|
||||
if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
|
||||
return cpufreq_table_find_index_al(policy, target_freq);
|
||||
else
|
||||
return cpufreq_table_find_index_dl(policy, target_freq);
|
||||
}
|
||||
|
||||
/* Find highest freq at or below target in a table in ascending order */
|
||||
static inline int cpufreq_table_find_index_ah(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq)
|
||||
{
|
||||
struct cpufreq_frequency_table *table = policy->freq_table;
|
||||
unsigned int freq;
|
||||
int i, best = -1;
|
||||
|
||||
for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
freq = table[i].frequency;
|
||||
|
||||
if (freq == target_freq)
|
||||
return i;
|
||||
|
||||
if (freq < target_freq) {
|
||||
best = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No freq found below target_freq */
|
||||
if (best == -1)
|
||||
return i;
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/* Find highest freq at or below target in a table in descending order */
|
||||
static inline int cpufreq_table_find_index_dh(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq)
|
||||
{
|
||||
struct cpufreq_frequency_table *table = policy->freq_table;
|
||||
unsigned int freq;
|
||||
int i, best = -1;
|
||||
|
||||
for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
freq = table[i].frequency;
|
||||
|
||||
if (freq <= target_freq)
|
||||
return i;
|
||||
|
||||
best = i;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/* Works only on sorted freq-tables */
|
||||
static inline int cpufreq_table_find_index_h(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq)
|
||||
{
|
||||
target_freq = clamp_val(target_freq, policy->min, policy->max);
|
||||
|
||||
if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
|
||||
return cpufreq_table_find_index_ah(policy, target_freq);
|
||||
else
|
||||
return cpufreq_table_find_index_dh(policy, target_freq);
|
||||
}
|
||||
|
||||
/* Find closest freq to target in a table in ascending order */
|
||||
static inline int cpufreq_table_find_index_ac(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq)
|
||||
{
|
||||
struct cpufreq_frequency_table *table = policy->freq_table;
|
||||
unsigned int freq;
|
||||
int i, best = -1;
|
||||
|
||||
for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
freq = table[i].frequency;
|
||||
|
||||
if (freq == target_freq)
|
||||
return i;
|
||||
|
||||
if (freq < target_freq) {
|
||||
best = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No freq found below target_freq */
|
||||
if (best == -1)
|
||||
return i;
|
||||
|
||||
/* Choose the closest freq */
|
||||
if (target_freq - table[best].frequency > freq - target_freq)
|
||||
return i;
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/* Find closest freq to target in a table in descending order */
|
||||
static inline int cpufreq_table_find_index_dc(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq)
|
||||
{
|
||||
struct cpufreq_frequency_table *table = policy->freq_table;
|
||||
unsigned int freq;
|
||||
int i, best = -1;
|
||||
|
||||
for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
|
||||
freq = table[i].frequency;
|
||||
|
||||
if (freq == target_freq)
|
||||
return i;
|
||||
|
||||
if (freq > target_freq) {
|
||||
best = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No freq found above target_freq */
|
||||
if (best == -1)
|
||||
return i;
|
||||
|
||||
/* Choose the closest freq */
|
||||
if (table[best].frequency - target_freq > target_freq - freq)
|
||||
return i;
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/* Works only on sorted freq-tables */
|
||||
static inline int cpufreq_table_find_index_c(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq)
|
||||
{
|
||||
target_freq = clamp_val(target_freq, policy->min, policy->max);
|
||||
|
||||
if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
|
||||
return cpufreq_table_find_index_ac(policy, target_freq);
|
||||
else
|
||||
return cpufreq_table_find_index_dc(policy, target_freq);
|
||||
}
|
||||
|
||||
static inline int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
if (unlikely(policy->freq_table_sorted == CPUFREQ_TABLE_UNSORTED))
|
||||
return cpufreq_table_index_unsorted(policy, target_freq,
|
||||
relation);
|
||||
|
||||
switch (relation) {
|
||||
case CPUFREQ_RELATION_L:
|
||||
return cpufreq_table_find_index_l(policy, target_freq);
|
||||
case CPUFREQ_RELATION_H:
|
||||
return cpufreq_table_find_index_h(policy, target_freq);
|
||||
case CPUFREQ_RELATION_C:
|
||||
return cpufreq_table_find_index_c(policy, target_freq);
|
||||
default:
|
||||
pr_err("%s: Invalid relation: %d\n", __func__, relation);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline int cpufreq_boost_trigger_state(int state)
|
||||
{
|
||||
|
|
@ -617,8 +874,6 @@ static inline bool policy_has_boost_freq(struct cpufreq_policy *policy)
|
|||
return false;
|
||||
}
|
||||
#endif
|
||||
/* the following funtion is for cpufreq core use only */
|
||||
struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
|
||||
|
||||
/* the following are really really optional */
|
||||
extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue