Commit 589e8be9 authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Linus Torvalds

[PATCH] cpufreq: move frequency table helpers to extra module

The CPU frequency table helpers can easily be modularized --
especially as they are not needed on all architectures, or for
all drivers (even on x86 -- see longrun and gx-suspmod)
parent 4e075e50
...@@ -994,9 +994,19 @@ config CPU_FREQ_24_API ...@@ -994,9 +994,19 @@ config CPU_FREQ_24_API
If in doubt, say N. If in doubt, say N.
config CPU_FREQ_TABLE
tristate "CPU frequency table helpers"
depends on CPU_FREQ
default y
help
Many CPUFreq drivers use these helpers, so only say N here if
the CPUFreq driver of your choice doesn't need these helpers.
If in doubt, say Y.
config X86_ACPI_CPUFREQ config X86_ACPI_CPUFREQ
tristate "ACPI Processor P-States driver" tristate "ACPI Processor P-States driver"
depends on CPU_FREQ && ACPI_PROCESSOR depends on CPU_FREQ_TABLE && ACPI_PROCESSOR
help help
This driver adds a CPUFreq driver which utilizes the ACPI This driver adds a CPUFreq driver which utilizes the ACPI
Processor Performance States. Processor Performance States.
...@@ -1007,7 +1017,7 @@ config X86_ACPI_CPUFREQ ...@@ -1007,7 +1017,7 @@ config X86_ACPI_CPUFREQ
config X86_POWERNOW_K6 config X86_POWERNOW_K6
tristate "AMD Mobile K6-2/K6-3 PowerNow!" tristate "AMD Mobile K6-2/K6-3 PowerNow!"
depends on CPU_FREQ depends on CPU_FREQ_TABLE
help help
This adds the CPUFreq driver for mobile AMD K6-2+ and mobile This adds the CPUFreq driver for mobile AMD K6-2+ and mobile
AMD K6-3+ processors. AMD K6-3+ processors.
...@@ -1018,7 +1028,7 @@ config X86_POWERNOW_K6 ...@@ -1018,7 +1028,7 @@ config X86_POWERNOW_K6
config X86_POWERNOW_K7 config X86_POWERNOW_K7
tristate "AMD Mobile Athlon/Duron PowerNow!" tristate "AMD Mobile Athlon/Duron PowerNow!"
depends on CPU_FREQ depends on CPU_FREQ_TABLE
help help
This adds the CPUFreq driver for mobile AMD K7 mobile processors. This adds the CPUFreq driver for mobile AMD K7 mobile processors.
...@@ -1028,7 +1038,7 @@ config X86_POWERNOW_K7 ...@@ -1028,7 +1038,7 @@ config X86_POWERNOW_K7
config ELAN_CPUFREQ config ELAN_CPUFREQ
tristate "AMD Elan" tristate "AMD Elan"
depends on CPU_FREQ && MELAN depends on CPU_FREQ_TABLE && MELAN
---help--- ---help---
This adds the CPUFreq driver for AMD Elan SC400 and SC410 This adds the CPUFreq driver for AMD Elan SC400 and SC410
processors. processors.
...@@ -1055,7 +1065,7 @@ config X86_LONGHAUL ...@@ -1055,7 +1065,7 @@ config X86_LONGHAUL
config X86_SPEEDSTEP config X86_SPEEDSTEP
tristate "Intel Speedstep" tristate "Intel Speedstep"
depends on CPU_FREQ depends on CPU_FREQ_TABLE
help help
This adds the CPUFreq driver for certain mobile Intel Pentium III This adds the CPUFreq driver for certain mobile Intel Pentium III
(Coppermine), all mobile Intel Pentium III-M (Tulatin) and all (Coppermine), all mobile Intel Pentium III-M (Tulatin) and all
...@@ -1067,7 +1077,7 @@ config X86_SPEEDSTEP ...@@ -1067,7 +1077,7 @@ config X86_SPEEDSTEP
config X86_P4_CLOCKMOD config X86_P4_CLOCKMOD
tristate "Intel Pentium 4 clock modulation" tristate "Intel Pentium 4 clock modulation"
depends on CPU_FREQ depends on CPU_FREQ_TABLE
help help
This adds the CPUFreq driver for Intel Pentium 4 / XEON This adds the CPUFreq driver for Intel Pentium 4 / XEON
processors. processors.
......
...@@ -162,9 +162,14 @@ config CPU_FREQ_PROC_INTF ...@@ -162,9 +162,14 @@ config CPU_FREQ_PROC_INTF
If in doubt, say N. If in doubt, say N.
config CPU_FREQ_TABLE
tristate
default y
config US3_FREQ config US3_FREQ
tristate "UltraSPARC-III CPU Frequency driver" tristate "UltraSPARC-III CPU Frequency driver"
depends on CPU_FREQ depends on CPU_FREQ_TABLE
help help
This adds the CPUFreq driver for UltraSPARC-III processors. This adds the CPUFreq driver for UltraSPARC-III processors.
......
...@@ -45,3 +45,4 @@ obj-$(CONFIG_HOTPLUG_PCI) += hotplug/ ...@@ -45,3 +45,4 @@ obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
obj-$(CONFIG_ISDN_BOOL) += isdn/ obj-$(CONFIG_ISDN_BOOL) += isdn/
obj-$(CONFIG_MCA) += mca/ obj-$(CONFIG_MCA) += mca/
obj-$(CONFIG_EISA) += eisa/ obj-$(CONFIG_EISA) += eisa/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
#CPUfreq governors and cross-arch helpers
obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
/*
* linux/drivers/cpufreq/freq_table.c
*
* Copyright (C) 2002 - 2003 Dominik Brodowski
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cpufreq.h>
/*********************************************************************
* FREQUENCY TABLE HELPERS *
*********************************************************************/
int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table)
{
unsigned int min_freq = ~0;
unsigned int max_freq = 0;
unsigned int i = 0;
for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
unsigned int freq = table[i].frequency;
if (freq == CPUFREQ_ENTRY_INVALID)
continue;
if (freq < min_freq)
min_freq = freq;
if (freq > max_freq)
max_freq = freq;
}
policy->min = policy->cpuinfo.min_freq = min_freq;
policy->max = policy->cpuinfo.max_freq = max_freq;
if (policy->min == ~0)
return -EINVAL;
else
return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table)
{
unsigned int next_larger = ~0;
unsigned int i = 0;
unsigned int count = 0;
if (!cpu_online(policy->cpu))
return -EINVAL;
cpufreq_verify_within_limits(policy,
policy->cpuinfo.min_freq,
policy->cpuinfo.max_freq);
for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
unsigned int freq = table[i].frequency;
if (freq == CPUFREQ_ENTRY_INVALID)
continue;
if ((freq >= policy->min) && (freq <= policy->max))
count++;
else if ((next_larger > freq) && (freq > policy->max))
next_larger = freq;
}
if (!count)
policy->max = next_larger;
cpufreq_verify_within_limits(policy,
policy->cpuinfo.min_freq,
policy->cpuinfo.max_freq);
return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table,
unsigned int *index)
{
struct cpufreq_frequency_table optimal = { .index = ~0, };
unsigned int i;
switch (policy->policy) {
case CPUFREQ_POLICY_PERFORMANCE:
optimal.frequency = 0;
break;
case CPUFREQ_POLICY_POWERSAVE:
optimal.frequency = ~0;
break;
}
if (!cpu_online(policy->cpu))
return -EINVAL;
for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
unsigned int freq = table[i].frequency;
if (freq == CPUFREQ_ENTRY_INVALID)
continue;
if ((freq < policy->min) || (freq > policy->max))
continue;
switch(policy->policy) {
case CPUFREQ_POLICY_PERFORMANCE:
if (optimal.frequency <= freq) {
optimal.frequency = freq;
optimal.index = i;
}
break;
case CPUFREQ_POLICY_POWERSAVE:
if (optimal.frequency >= freq) {
optimal.frequency = freq;
optimal.index = i;
}
break;
}
}
if (optimal.index > i)
return -EINVAL;
*index = optimal.index;
return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy);
int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table,
unsigned int target_freq,
unsigned int relation,
unsigned int *index)
{
struct cpufreq_frequency_table optimal = { .index = ~0, };
struct cpufreq_frequency_table suboptimal = { .index = ~0, };
unsigned int i;
switch (relation) {
case CPUFREQ_RELATION_H:
optimal.frequency = 0;
suboptimal.frequency = ~0;
break;
case CPUFREQ_RELATION_L:
optimal.frequency = ~0;
suboptimal.frequency = 0;
break;
}
if (!cpu_online(policy->cpu))
return -EINVAL;
for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
unsigned int freq = table[i].frequency;
if (freq == CPUFREQ_ENTRY_INVALID)
continue;
if ((freq < policy->min) || (freq > policy->max))
continue;
switch(relation) {
case CPUFREQ_RELATION_H:
if (freq <= target_freq) {
if (freq >= optimal.frequency) {
optimal.frequency = freq;
optimal.index = i;
}
} else {
if (freq <= suboptimal.frequency) {
suboptimal.frequency = freq;
suboptimal.index = i;
}
}
break;
case CPUFREQ_RELATION_L:
if (freq >= target_freq) {
if (freq <= optimal.frequency) {
optimal.frequency = freq;
optimal.index = i;
}
} else {
if (freq >= suboptimal.frequency) {
suboptimal.frequency = freq;
suboptimal.index = i;
}
}
break;
}
}
if (optimal.index > i) {
if (suboptimal.index > i)
return -EINVAL;
*index = suboptimal.index;
} else
*index = optimal.index;
return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
MODULE_DESCRIPTION ("CPUfreq frequency table helpers");
MODULE_LICENSE ("GPL");
...@@ -297,6 +297,7 @@ enum { ...@@ -297,6 +297,7 @@ enum {
#endif /* CONFIG_CPU_FREQ_24_API */ #endif /* CONFIG_CPU_FREQ_24_API */
#if defined(CONFIG_CPU_FREQ_TABLE) || defined(CONFIG_CPU_FREQ_TABLE_MODULE)
/********************************************************************* /*********************************************************************
* FREQUENCY TABLE HELPERS * * FREQUENCY TABLE HELPERS *
*********************************************************************/ *********************************************************************/
...@@ -326,4 +327,6 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, ...@@ -326,4 +327,6 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
unsigned int relation, unsigned int relation,
unsigned int *index); unsigned int *index);
#endif /* CONFIG_CPU_FREQ_TABLE */
#endif /* _LINUX_CPUFREQ_H */ #endif /* _LINUX_CPUFREQ_H */
...@@ -1582,191 +1582,3 @@ EXPORT_SYMBOL_GPL(cpufreq_restore); ...@@ -1582,191 +1582,3 @@ EXPORT_SYMBOL_GPL(cpufreq_restore);
#else #else
#define cpufreq_restore() do {} while (0) #define cpufreq_restore() do {} while (0)
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
/*********************************************************************
* FREQUENCY TABLE HELPERS *
*********************************************************************/
int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table)
{
unsigned int min_freq = ~0;
unsigned int max_freq = 0;
unsigned int i = 0;
for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
unsigned int freq = table[i].frequency;
if (freq == CPUFREQ_ENTRY_INVALID)
continue;
if (freq < min_freq)
min_freq = freq;
if (freq > max_freq)
max_freq = freq;
}
policy->min = policy->cpuinfo.min_freq = min_freq;
policy->max = policy->cpuinfo.max_freq = max_freq;
if (policy->min == ~0)
return -EINVAL;
else
return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table)
{
unsigned int next_larger = ~0;
unsigned int i = 0;
unsigned int count = 0;
if (!cpu_online(policy->cpu))
return -EINVAL;
cpufreq_verify_within_limits(policy,
policy->cpuinfo.min_freq,
policy->cpuinfo.max_freq);
for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
unsigned int freq = table[i].frequency;
if (freq == CPUFREQ_ENTRY_INVALID)
continue;
if ((freq >= policy->min) && (freq <= policy->max))
count++;
else if ((next_larger > freq) && (freq > policy->max))
next_larger = freq;
}
if (!count)
policy->max = next_larger;
cpufreq_verify_within_limits(policy,
policy->cpuinfo.min_freq,
policy->cpuinfo.max_freq);
return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table,
unsigned int *index)
{
struct cpufreq_frequency_table optimal = { .index = ~0, };
unsigned int i;
switch (policy->policy) {
case CPUFREQ_POLICY_PERFORMANCE:
optimal.frequency = 0;
break;
case CPUFREQ_POLICY_POWERSAVE:
optimal.frequency = ~0;
break;
}
if (!cpu_online(policy->cpu))
return -EINVAL;
for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
unsigned int freq = table[i].frequency;
if (freq == CPUFREQ_ENTRY_INVALID)
continue;
if ((freq < policy->min) || (freq > policy->max))
continue;
switch(policy->policy) {
case CPUFREQ_POLICY_PERFORMANCE:
if (optimal.frequency <= freq) {
optimal.frequency = freq;
optimal.index = i;
}
break;
case CPUFREQ_POLICY_POWERSAVE:
if (optimal.frequency >= freq) {
optimal.frequency = freq;
optimal.index = i;
}
break;
}
}
if (optimal.index > i)
return -EINVAL;
*index = optimal.index;
return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy);
int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table,
unsigned int target_freq,
unsigned int relation,
unsigned int *index)
{
struct cpufreq_frequency_table optimal = { .index = ~0, };
struct cpufreq_frequency_table suboptimal = { .index = ~0, };
unsigned int i;
switch (relation) {
case CPUFREQ_RELATION_H:
optimal.frequency = 0;
suboptimal.frequency = ~0;
break;
case CPUFREQ_RELATION_L:
optimal.frequency = ~0;
suboptimal.frequency = 0;
break;
}
if (!cpu_online(policy->cpu))
return -EINVAL;
for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
unsigned int freq = table[i].frequency;
if (freq == CPUFREQ_ENTRY_INVALID)
continue;
if ((freq < policy->min) || (freq > policy->max))
continue;
switch(relation) {
case CPUFREQ_RELATION_H:
if (freq <= target_freq) {
if (freq >= optimal.frequency) {
optimal.frequency = freq;
optimal.index = i;
}
} else {
if (freq <= suboptimal.frequency) {
suboptimal.frequency = freq;
suboptimal.index = i;
}
}
break;
case CPUFREQ_RELATION_L:
if (freq >= target_freq) {
if (freq <= optimal.frequency) {
optimal.frequency = freq;
optimal.index = i;
}
} else {
if (freq >= suboptimal.frequency) {
suboptimal.frequency = freq;
suboptimal.index = i;
}
}
break;
}
}
if (optimal.index > i) {
if (suboptimal.index > i)
return -EINVAL;
*index = suboptimal.index;
} else
*index = optimal.index;
return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
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