Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
* master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq: [CPUFREQ] Fix typos in powernow-k8 printk's. [CPUFREQ] Restore previously used governor on a hot-replugged CPU [CPUFREQ] bugfix cpufreq in combination with performance governor [CPUFREQ] powernow-k8 compile fix. [CPUFREQ] the overdue removal of X86_SPEEDSTEP_CENTRINO_ACPI [CPUFREQ] Longhaul - Option to disable ACPI C3 support Fixed up arch/i386/kernel/cpu/cpufreq/powernow-k8.c due to revert that got fixed differently in the cpufreq branch. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Коммит
af09f1e4b3
|
@ -196,28 +196,6 @@ Who: Adrian Bunk <bunk@stusta.de>
|
|||
|
||||
---------------------------
|
||||
|
||||
What: ACPI hooks (X86_SPEEDSTEP_CENTRINO_ACPI) in speedstep-centrino driver
|
||||
When: December 2006
|
||||
Why: Speedstep-centrino driver with ACPI hooks and acpi-cpufreq driver are
|
||||
functionally very much similar. They talk to ACPI in same way. Only
|
||||
difference between them is the way they do frequency transitions.
|
||||
One uses MSRs and the other one uses IO ports. Functionaliy of
|
||||
speedstep_centrino with ACPI hooks is now merged into acpi-cpufreq.
|
||||
That means one common driver will support all Intel Enhanced Speedstep
|
||||
capable CPUs. That means less confusion over name of
|
||||
speedstep-centrino driver (with that driver supposed to be used on
|
||||
non-centrino platforms). That means less duplication of code and
|
||||
less maintenance effort and no possibility of these two drivers
|
||||
going out of sync.
|
||||
Current users of speedstep_centrino with ACPI hooks are requested to
|
||||
switch over to acpi-cpufreq driver. speedstep-centrino will continue
|
||||
to work using older non-ACPI static table based scheme even after this
|
||||
date.
|
||||
|
||||
Who: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: /sys/firmware/acpi/namespace
|
||||
When: 2.6.21
|
||||
Why: The ACPI namespace is effectively the symbol list for
|
||||
|
|
|
@ -116,7 +116,7 @@ config X86_GX_SUSPMOD
|
|||
config X86_SPEEDSTEP_CENTRINO
|
||||
tristate "Intel Enhanced SpeedStep"
|
||||
select CPU_FREQ_TABLE
|
||||
select X86_SPEEDSTEP_CENTRINO_TABLE if (!X86_SPEEDSTEP_CENTRINO_ACPI)
|
||||
select X86_SPEEDSTEP_CENTRINO_TABLE
|
||||
help
|
||||
This adds the CPUFreq driver for Enhanced SpeedStep enabled
|
||||
mobile CPUs. This means Intel Pentium M (Centrino) CPUs. However,
|
||||
|
@ -128,20 +128,6 @@ config X86_SPEEDSTEP_CENTRINO
|
|||
|
||||
If in doubt, say N.
|
||||
|
||||
config X86_SPEEDSTEP_CENTRINO_ACPI
|
||||
bool "Use ACPI tables to decode valid frequency/voltage (deprecated)"
|
||||
depends on X86_SPEEDSTEP_CENTRINO && ACPI_PROCESSOR
|
||||
depends on !(X86_SPEEDSTEP_CENTRINO = y && ACPI_PROCESSOR = m)
|
||||
help
|
||||
This is deprecated and this functionality is now merged into
|
||||
acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of
|
||||
speedstep_centrino.
|
||||
Use primarily the information provided in the BIOS ACPI tables
|
||||
to determine valid CPU frequency and voltage pairings. It is
|
||||
required for the driver to work on non-Banias CPUs.
|
||||
|
||||
If in doubt, say Y.
|
||||
|
||||
config X86_SPEEDSTEP_CENTRINO_TABLE
|
||||
bool "Built-in tables for Banias CPUs"
|
||||
depends on X86_SPEEDSTEP_CENTRINO
|
||||
|
@ -237,7 +223,7 @@ comment "shared options"
|
|||
config X86_ACPI_CPUFREQ_PROC_INTF
|
||||
bool "/proc/acpi/processor/../performance interface (deprecated)"
|
||||
depends on PROC_FS
|
||||
depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
|
||||
depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
|
||||
help
|
||||
This enables the deprecated /proc/acpi/processor/../performance
|
||||
interface. While it is helpful for debugging, the generic,
|
||||
|
|
|
@ -75,6 +75,7 @@ static unsigned int longhaul_index;
|
|||
|
||||
/* Module parameters */
|
||||
static int scale_voltage;
|
||||
static int disable_acpi_c3;
|
||||
|
||||
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
|
||||
|
||||
|
@ -844,6 +845,9 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
|
|||
if (cx->address > 0 && cx->latency <= 1000)
|
||||
longhaul_flags |= USE_ACPI_C3;
|
||||
}
|
||||
/* Disable if it isn't working */
|
||||
if (disable_acpi_c3)
|
||||
longhaul_flags &= ~USE_ACPI_C3;
|
||||
/* Check if northbridge is friendly */
|
||||
if (enable_arbiter_disable())
|
||||
longhaul_flags |= USE_NORTHBRIDGE;
|
||||
|
@ -952,6 +956,9 @@ static void __exit longhaul_exit(void)
|
|||
kfree(longhaul_table);
|
||||
}
|
||||
|
||||
module_param (disable_acpi_c3, int, 0644);
|
||||
MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support");
|
||||
|
||||
module_param (scale_voltage, int, 0644);
|
||||
MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
|
||||
|
||||
|
|
|
@ -599,11 +599,14 @@ static void print_basics(struct powernow_k8_data *data)
|
|||
for (j = 0; j < data->numps; j++) {
|
||||
if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) {
|
||||
if (cpu_family == CPU_HW_PSTATE) {
|
||||
printk(KERN_INFO PFX " %d : fid 0x%x gid 0x%x (%d MHz)\n", j, (data->powernow_table[j].index & 0xff00) >> 8,
|
||||
printk(KERN_INFO PFX " %d : fid 0x%x did 0x%x (%d MHz)\n",
|
||||
j,
|
||||
(data->powernow_table[j].index & 0xff00) >> 8,
|
||||
(data->powernow_table[j].index & 0xff0000) >> 16,
|
||||
data->powernow_table[j].frequency/1000);
|
||||
} else {
|
||||
printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n", j,
|
||||
printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n",
|
||||
j,
|
||||
data->powernow_table[j].index & 0xff,
|
||||
data->powernow_table[j].frequency/1000,
|
||||
data->powernow_table[j].index >> 8);
|
||||
|
@ -1086,7 +1089,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
|
|||
|
||||
if (cpu_family == CPU_HW_PSTATE)
|
||||
dprintk("targ: curr fid 0x%x, did 0x%x\n",
|
||||
data->currfid, data->currvid);
|
||||
data->currfid, data->currdid);
|
||||
else {
|
||||
dprintk("targ: curr fid 0x%x, vid 0x%x\n",
|
||||
data->currfid, data->currvid);
|
||||
|
@ -1322,16 +1325,22 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
|
|||
static int __cpuinit powernowk8_init(void)
|
||||
{
|
||||
unsigned int i, supported_cpus = 0;
|
||||
unsigned int booted_cores = 1;
|
||||
|
||||
for_each_online_cpu(i) {
|
||||
if (check_supported_cpu(i))
|
||||
supported_cpus++;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
booted_cores = cpu_data[0].booted_cores;
|
||||
#endif
|
||||
|
||||
if (supported_cpus == num_online_cpus()) {
|
||||
printk(KERN_INFO PFX "Found %d %s "
|
||||
"processors (" VERSION ")\n", supported_cpus,
|
||||
boot_cpu_data.x86_model_id);
|
||||
"processors (%d cpu cores) (" VERSION ")\n",
|
||||
supported_cpus/booted_cores,
|
||||
boot_cpu_data.x86_model_id, supported_cpus);
|
||||
return cpufreq_register_driver(&cpufreq_amd64_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,12 +21,6 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <acpi/processor.h>
|
||||
#endif
|
||||
|
||||
#include <asm/msr.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/cpufeature.h>
|
||||
|
@ -257,9 +251,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
|
|||
/* Matched a non-match */
|
||||
dprintk("no table support for CPU model \"%s\"\n",
|
||||
cpu->x86_model_id);
|
||||
#ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
|
||||
dprintk("try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
|
||||
#endif
|
||||
dprintk("try using the acpi-cpufreq driver\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
@ -346,213 +338,6 @@ static unsigned int get_cur_freq(unsigned int cpu)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
|
||||
|
||||
static struct acpi_processor_performance *acpi_perf_data[NR_CPUS];
|
||||
|
||||
/*
|
||||
* centrino_cpu_early_init_acpi - Do the preregistering with ACPI P-States
|
||||
* library
|
||||
*
|
||||
* Before doing the actual init, we need to do _PSD related setup whenever
|
||||
* supported by the BIOS. These are handled by this early_init routine.
|
||||
*/
|
||||
static int centrino_cpu_early_init_acpi(void)
|
||||
{
|
||||
unsigned int i, j;
|
||||
struct acpi_processor_performance *data;
|
||||
|
||||
for_each_possible_cpu(i) {
|
||||
data = kzalloc(sizeof(struct acpi_processor_performance),
|
||||
GFP_KERNEL);
|
||||
if (!data) {
|
||||
for_each_possible_cpu(j) {
|
||||
kfree(acpi_perf_data[j]);
|
||||
acpi_perf_data[j] = NULL;
|
||||
}
|
||||
return (-ENOMEM);
|
||||
}
|
||||
acpi_perf_data[i] = data;
|
||||
}
|
||||
|
||||
acpi_processor_preregister_performance(acpi_perf_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* Some BIOSes do SW_ANY coordination internally, either set it up in hw
|
||||
* or do it in BIOS firmware and won't inform about it to OS. If not
|
||||
* detected, this has a side effect of making CPU run at a different speed
|
||||
* than OS intended it to run at. Detect it and handle it cleanly.
|
||||
*/
|
||||
static int bios_with_sw_any_bug;
|
||||
static int sw_any_bug_found(struct dmi_system_id *d)
|
||||
{
|
||||
bios_with_sw_any_bug = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dmi_system_id sw_any_bug_dmi_table[] = {
|
||||
{
|
||||
.callback = sw_any_bug_found,
|
||||
.ident = "Supermicro Server X6DLP",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "080010"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* centrino_cpu_init_acpi - register with ACPI P-States library
|
||||
*
|
||||
* Register with the ACPI P-States library (part of drivers/acpi/processor.c)
|
||||
* in order to determine correct frequency and voltage pairings by reading
|
||||
* the _PSS of the ACPI DSDT or SSDT tables.
|
||||
*/
|
||||
static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned long cur_freq;
|
||||
int result = 0, i;
|
||||
unsigned int cpu = policy->cpu;
|
||||
struct acpi_processor_performance *p;
|
||||
|
||||
p = acpi_perf_data[cpu];
|
||||
|
||||
/* register with ACPI core */
|
||||
if (acpi_processor_register_performance(p, cpu)) {
|
||||
dprintk(PFX "obtaining ACPI data failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
policy->shared_type = p->shared_type;
|
||||
/*
|
||||
* Will let policy->cpus know about dependency only when software
|
||||
* coordination is required.
|
||||
*/
|
||||
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
|
||||
policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
|
||||
policy->cpus = p->shared_cpu_map;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
dmi_check_system(sw_any_bug_dmi_table);
|
||||
if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) {
|
||||
policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
|
||||
policy->cpus = cpu_core_map[cpu];
|
||||
}
|
||||
#endif
|
||||
|
||||
/* verify the acpi_data */
|
||||
if (p->state_count <= 1) {
|
||||
dprintk("No P-States\n");
|
||||
result = -ENODEV;
|
||||
goto err_unreg;
|
||||
}
|
||||
|
||||
if ((p->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
|
||||
(p->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
|
||||
dprintk("Invalid control/status registers (%x - %x)\n",
|
||||
p->control_register.space_id, p->status_register.space_id);
|
||||
result = -EIO;
|
||||
goto err_unreg;
|
||||
}
|
||||
|
||||
for (i=0; i<p->state_count; i++) {
|
||||
if ((p->states[i].control & INTEL_MSR_RANGE) !=
|
||||
(p->states[i].status & INTEL_MSR_RANGE)) {
|
||||
dprintk("Different MSR bits in control (%llu) and status (%llu)\n",
|
||||
p->states[i].control, p->states[i].status);
|
||||
result = -EINVAL;
|
||||
goto err_unreg;
|
||||
}
|
||||
|
||||
if (!p->states[i].core_frequency) {
|
||||
dprintk("Zero core frequency for state %u\n", i);
|
||||
result = -EINVAL;
|
||||
goto err_unreg;
|
||||
}
|
||||
|
||||
if (p->states[i].core_frequency > p->states[0].core_frequency) {
|
||||
dprintk("P%u has larger frequency (%llu) than P0 (%llu), skipping\n", i,
|
||||
p->states[i].core_frequency, p->states[0].core_frequency);
|
||||
p->states[i].core_frequency = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
centrino_model[cpu] = kzalloc(sizeof(struct cpu_model), GFP_KERNEL);
|
||||
if (!centrino_model[cpu]) {
|
||||
result = -ENOMEM;
|
||||
goto err_unreg;
|
||||
}
|
||||
|
||||
centrino_model[cpu]->model_name=NULL;
|
||||
centrino_model[cpu]->max_freq = p->states[0].core_frequency * 1000;
|
||||
centrino_model[cpu]->op_points = kmalloc(sizeof(struct cpufreq_frequency_table) *
|
||||
(p->state_count + 1), GFP_KERNEL);
|
||||
if (!centrino_model[cpu]->op_points) {
|
||||
result = -ENOMEM;
|
||||
goto err_kfree;
|
||||
}
|
||||
|
||||
for (i=0; i<p->state_count; i++) {
|
||||
centrino_model[cpu]->op_points[i].index = p->states[i].control & INTEL_MSR_RANGE;
|
||||
centrino_model[cpu]->op_points[i].frequency = p->states[i].core_frequency * 1000;
|
||||
dprintk("adding state %i with frequency %u and control value %04x\n",
|
||||
i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index);
|
||||
}
|
||||
centrino_model[cpu]->op_points[p->state_count].frequency = CPUFREQ_TABLE_END;
|
||||
|
||||
cur_freq = get_cur_freq(cpu);
|
||||
|
||||
for (i=0; i<p->state_count; i++) {
|
||||
if (!p->states[i].core_frequency) {
|
||||
dprintk("skipping state %u\n", i);
|
||||
centrino_model[cpu]->op_points[i].frequency = CPUFREQ_ENTRY_INVALID;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0) !=
|
||||
(centrino_model[cpu]->op_points[i].frequency)) {
|
||||
dprintk("Invalid encoded frequency (%u vs. %u)\n",
|
||||
extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0),
|
||||
centrino_model[cpu]->op_points[i].frequency);
|
||||
result = -EINVAL;
|
||||
goto err_kfree_all;
|
||||
}
|
||||
|
||||
if (cur_freq == centrino_model[cpu]->op_points[i].frequency)
|
||||
p->state = i;
|
||||
}
|
||||
|
||||
/* notify BIOS that we exist */
|
||||
acpi_processor_notify_smm(THIS_MODULE);
|
||||
printk("speedstep-centrino with X86_SPEEDSTEP_CENTRINO_ACPI "
|
||||
"config is deprecated.\n "
|
||||
"Use X86_ACPI_CPUFREQ (acpi-cpufreq) instead.\n" );
|
||||
|
||||
return 0;
|
||||
|
||||
err_kfree_all:
|
||||
kfree(centrino_model[cpu]->op_points);
|
||||
err_kfree:
|
||||
kfree(centrino_model[cpu]);
|
||||
err_unreg:
|
||||
acpi_processor_unregister_performance(p, cpu);
|
||||
dprintk(PFX "invalid ACPI data\n");
|
||||
return (result);
|
||||
}
|
||||
#else
|
||||
static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; }
|
||||
static inline int centrino_cpu_early_init_acpi(void) { return 0; }
|
||||
#endif
|
||||
|
||||
static int centrino_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
|
||||
|
@ -568,7 +353,6 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
|
|||
if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC))
|
||||
centrino_driver.flags |= CPUFREQ_CONST_LOOPS;
|
||||
|
||||
if (centrino_cpu_init_acpi(policy)) {
|
||||
if (policy->cpu != 0)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -589,7 +373,6 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
|
|||
if (centrino_cpu_init_table(policy)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if Enhanced SpeedStep is enabled, and try to
|
||||
enable it if not. */
|
||||
|
@ -634,20 +417,6 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
|
|||
|
||||
cpufreq_frequency_table_put_attr(cpu);
|
||||
|
||||
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
|
||||
if (!centrino_model[cpu]->model_name) {
|
||||
static struct acpi_processor_performance *p;
|
||||
|
||||
if (acpi_perf_data[cpu]) {
|
||||
p = acpi_perf_data[cpu];
|
||||
dprintk("unregistering and freeing ACPI data\n");
|
||||
acpi_processor_unregister_performance(p, cpu);
|
||||
kfree(centrino_model[cpu]->op_points);
|
||||
kfree(centrino_model[cpu]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
centrino_model[cpu] = NULL;
|
||||
|
||||
return 0;
|
||||
|
@ -849,25 +618,12 @@ static int __init centrino_init(void)
|
|||
if (!cpu_has(cpu, X86_FEATURE_EST))
|
||||
return -ENODEV;
|
||||
|
||||
centrino_cpu_early_init_acpi();
|
||||
|
||||
return cpufreq_register_driver(¢rino_driver);
|
||||
}
|
||||
|
||||
static void __exit centrino_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
|
||||
unsigned int j;
|
||||
#endif
|
||||
|
||||
cpufreq_unregister_driver(¢rino_driver);
|
||||
|
||||
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
|
||||
for_each_possible_cpu(j) {
|
||||
kfree(acpi_perf_data[j]);
|
||||
acpi_perf_data[j] = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
MODULE_AUTHOR ("Jeremy Fitzhardinge <jeremy@goop.org>");
|
||||
|
|
|
@ -48,10 +48,6 @@ config X86_SPEEDSTEP_CENTRINO
|
|||
|
||||
If in doubt, say N.
|
||||
|
||||
config X86_SPEEDSTEP_CENTRINO_ACPI
|
||||
bool
|
||||
depends on X86_SPEEDSTEP_CENTRINO
|
||||
|
||||
config X86_ACPI_CPUFREQ
|
||||
tristate "ACPI Processor P-States driver"
|
||||
select CPU_FREQ_TABLE
|
||||
|
@ -73,7 +69,7 @@ comment "shared options"
|
|||
config X86_ACPI_CPUFREQ_PROC_INTF
|
||||
bool "/proc/acpi/processor/../performance interface (deprecated)"
|
||||
depends on PROC_FS
|
||||
depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K8_ACPI
|
||||
depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K8_ACPI
|
||||
help
|
||||
This enables the deprecated /proc/acpi/processor/../performance
|
||||
interface. While it is helpful for debugging, the generic,
|
||||
|
|
|
@ -39,6 +39,10 @@
|
|||
*/
|
||||
static struct cpufreq_driver *cpufreq_driver;
|
||||
static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
/* This one keeps track of the previously set governor of a removed CPU */
|
||||
static struct cpufreq_governor *cpufreq_cpu_governor[NR_CPUS];
|
||||
#endif
|
||||
static DEFINE_SPINLOCK(cpufreq_driver_lock);
|
||||
|
||||
/*
|
||||
|
@ -770,9 +774,17 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
|
|||
}
|
||||
policy->user_policy.min = policy->cpuinfo.min_freq;
|
||||
policy->user_policy.max = policy->cpuinfo.max_freq;
|
||||
policy->user_policy.governor = policy->governor;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
if (cpufreq_cpu_governor[cpu]){
|
||||
policy->governor = cpufreq_cpu_governor[cpu];
|
||||
dprintk("Restoring governor %s for cpu %d\n",
|
||||
policy->governor->name, cpu);
|
||||
}
|
||||
#endif
|
||||
|
||||
for_each_cpu_mask(j, policy->cpus) {
|
||||
if (cpu == j)
|
||||
continue;
|
||||
|
@ -873,6 +885,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
|
|||
/* set default policy */
|
||||
ret = __cpufreq_set_policy(policy, &new_policy);
|
||||
policy->user_policy.policy = policy->policy;
|
||||
policy->user_policy.governor = policy->governor;
|
||||
|
||||
unlock_policy_rwsem_write(cpu);
|
||||
|
||||
|
@ -969,6 +982,11 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
cpufreq_cpu_governor[cpu] = data->governor;
|
||||
#endif
|
||||
|
||||
/* if we have other CPUs still registered, we need to unlink them,
|
||||
* or else wait_for_completion below will lock up. Clean the
|
||||
* cpufreq_cpu_data[] while holding the lock, and remove the sysfs
|
||||
|
@ -989,6 +1007,9 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev)
|
|||
if (j == cpu)
|
||||
continue;
|
||||
dprintk("removing link for cpu %u\n", j);
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
cpufreq_cpu_governor[j] = data->governor;
|
||||
#endif
|
||||
cpu_sys_dev = get_cpu_sysdev(j);
|
||||
sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq");
|
||||
cpufreq_cpu_put(data);
|
||||
|
@ -1687,7 +1708,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
|
|||
{
|
||||
unsigned int cpu = (unsigned long)hcpu;
|
||||
struct sys_device *sys_dev;
|
||||
struct cpufreq_policy *policy;
|
||||
|
||||
sys_dev = get_cpu_sysdev(cpu);
|
||||
if (sys_dev) {
|
||||
|
@ -1701,11 +1721,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
|
|||
if (unlikely(lock_policy_rwsem_write(cpu)))
|
||||
BUG();
|
||||
|
||||
policy = cpufreq_cpu_data[cpu];
|
||||
if (policy) {
|
||||
__cpufreq_driver_target(policy, policy->min,
|
||||
CPUFREQ_RELATION_H);
|
||||
}
|
||||
__cpufreq_remove_dev(sys_dev);
|
||||
break;
|
||||
case CPU_DOWN_FAILED:
|
||||
|
|
Загрузка…
Ссылка в новой задаче