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:
Linus Torvalds 2007-07-13 16:06:30 -07:00
commit af09f1e4b3
7 changed files with 67 additions and 320 deletions

View file

@ -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 What: /sys/firmware/acpi/namespace
When: 2.6.21 When: 2.6.21
Why: The ACPI namespace is effectively the symbol list for Why: The ACPI namespace is effectively the symbol list for

View file

@ -116,7 +116,7 @@ config X86_GX_SUSPMOD
config X86_SPEEDSTEP_CENTRINO config X86_SPEEDSTEP_CENTRINO
tristate "Intel Enhanced SpeedStep" tristate "Intel Enhanced SpeedStep"
select CPU_FREQ_TABLE select CPU_FREQ_TABLE
select X86_SPEEDSTEP_CENTRINO_TABLE if (!X86_SPEEDSTEP_CENTRINO_ACPI) select X86_SPEEDSTEP_CENTRINO_TABLE
help help
This adds the CPUFreq driver for Enhanced SpeedStep enabled This adds the CPUFreq driver for Enhanced SpeedStep enabled
mobile CPUs. This means Intel Pentium M (Centrino) CPUs. However, mobile CPUs. This means Intel Pentium M (Centrino) CPUs. However,
@ -128,20 +128,6 @@ config X86_SPEEDSTEP_CENTRINO
If in doubt, say N. 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 config X86_SPEEDSTEP_CENTRINO_TABLE
bool "Built-in tables for Banias CPUs" bool "Built-in tables for Banias CPUs"
depends on X86_SPEEDSTEP_CENTRINO depends on X86_SPEEDSTEP_CENTRINO
@ -237,7 +223,7 @@ comment "shared options"
config X86_ACPI_CPUFREQ_PROC_INTF config X86_ACPI_CPUFREQ_PROC_INTF
bool "/proc/acpi/processor/../performance interface (deprecated)" bool "/proc/acpi/processor/../performance interface (deprecated)"
depends on PROC_FS 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 help
This enables the deprecated /proc/acpi/processor/../performance This enables the deprecated /proc/acpi/processor/../performance
interface. While it is helpful for debugging, the generic, interface. While it is helpful for debugging, the generic,

View file

@ -75,6 +75,7 @@ static unsigned int longhaul_index;
/* Module parameters */ /* Module parameters */
static int scale_voltage; static int scale_voltage;
static int disable_acpi_c3;
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) #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) if (cx->address > 0 && cx->latency <= 1000)
longhaul_flags |= USE_ACPI_C3; 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 */ /* Check if northbridge is friendly */
if (enable_arbiter_disable()) if (enable_arbiter_disable())
longhaul_flags |= USE_NORTHBRIDGE; longhaul_flags |= USE_NORTHBRIDGE;
@ -952,6 +956,9 @@ static void __exit longhaul_exit(void)
kfree(longhaul_table); 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_param (scale_voltage, int, 0644);
MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");

View file

@ -599,14 +599,17 @@ static void print_basics(struct powernow_k8_data *data)
for (j = 0; j < data->numps; j++) { for (j = 0; j < data->numps; j++) {
if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) { if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) {
if (cpu_family == CPU_HW_PSTATE) { 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",
(data->powernow_table[j].index & 0xff0000) >> 16, j,
data->powernow_table[j].frequency/1000); (data->powernow_table[j].index & 0xff00) >> 8,
(data->powernow_table[j].index & 0xff0000) >> 16,
data->powernow_table[j].frequency/1000);
} else { } 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",
data->powernow_table[j].index & 0xff, j,
data->powernow_table[j].frequency/1000, data->powernow_table[j].index & 0xff,
data->powernow_table[j].index >> 8); 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) if (cpu_family == CPU_HW_PSTATE)
dprintk("targ: curr fid 0x%x, did 0x%x\n", dprintk("targ: curr fid 0x%x, did 0x%x\n",
data->currfid, data->currvid); data->currfid, data->currdid);
else { else {
dprintk("targ: curr fid 0x%x, vid 0x%x\n", dprintk("targ: curr fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid); data->currfid, data->currvid);
@ -1322,16 +1325,22 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
static int __cpuinit powernowk8_init(void) static int __cpuinit powernowk8_init(void)
{ {
unsigned int i, supported_cpus = 0; unsigned int i, supported_cpus = 0;
unsigned int booted_cores = 1;
for_each_online_cpu(i) { for_each_online_cpu(i) {
if (check_supported_cpu(i)) if (check_supported_cpu(i))
supported_cpus++; supported_cpus++;
} }
#ifdef CONFIG_SMP
booted_cores = cpu_data[0].booted_cores;
#endif
if (supported_cpus == num_online_cpus()) { if (supported_cpus == num_online_cpus()) {
printk(KERN_INFO PFX "Found %d %s " printk(KERN_INFO PFX "Found %d %s "
"processors (" VERSION ")\n", supported_cpus, "processors (%d cpu cores) (" VERSION ")\n",
boot_cpu_data.x86_model_id); supported_cpus/booted_cores,
boot_cpu_data.x86_model_id, supported_cpus);
return cpufreq_register_driver(&cpufreq_amd64_driver); return cpufreq_register_driver(&cpufreq_amd64_driver);
} }

View file

@ -21,12 +21,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/compiler.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/msr.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
@ -257,9 +251,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
/* Matched a non-match */ /* Matched a non-match */
dprintk("no table support for CPU model \"%s\"\n", dprintk("no table support for CPU model \"%s\"\n",
cpu->x86_model_id); cpu->x86_model_id);
#ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI dprintk("try using the acpi-cpufreq driver\n");
dprintk("try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
#endif
return -ENOENT; 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) static int centrino_cpu_init(struct cpufreq_policy *policy)
{ {
struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu]; struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
@ -568,27 +353,25 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC)) if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC))
centrino_driver.flags |= CPUFREQ_CONST_LOOPS; centrino_driver.flags |= CPUFREQ_CONST_LOOPS;
if (centrino_cpu_init_acpi(policy)) { if (policy->cpu != 0)
if (policy->cpu != 0) return -ENODEV;
return -ENODEV;
for (i = 0; i < N_IDS; i++) for (i = 0; i < N_IDS; i++)
if (centrino_verify_cpu_id(cpu, &cpu_ids[i])) if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
break; break;
if (i != N_IDS) if (i != N_IDS)
centrino_cpu[policy->cpu] = &cpu_ids[i]; centrino_cpu[policy->cpu] = &cpu_ids[i];
if (!centrino_cpu[policy->cpu]) { if (!centrino_cpu[policy->cpu]) {
dprintk("found unsupported CPU with " dprintk("found unsupported CPU with "
"Enhanced SpeedStep: send /proc/cpuinfo to " "Enhanced SpeedStep: send /proc/cpuinfo to "
MAINTAINER "\n"); MAINTAINER "\n");
return -ENODEV; return -ENODEV;
} }
if (centrino_cpu_init_table(policy)) { if (centrino_cpu_init_table(policy)) {
return -ENODEV; return -ENODEV;
}
} }
/* Check to see if Enhanced SpeedStep is enabled, and try to /* Check to see if Enhanced SpeedStep is enabled, and try to
@ -634,20 +417,6 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
cpufreq_frequency_table_put_attr(cpu); 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; centrino_model[cpu] = NULL;
return 0; return 0;
@ -849,25 +618,12 @@ static int __init centrino_init(void)
if (!cpu_has(cpu, X86_FEATURE_EST)) if (!cpu_has(cpu, X86_FEATURE_EST))
return -ENODEV; return -ENODEV;
centrino_cpu_early_init_acpi();
return cpufreq_register_driver(&centrino_driver); return cpufreq_register_driver(&centrino_driver);
} }
static void __exit centrino_exit(void) static void __exit centrino_exit(void)
{ {
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
unsigned int j;
#endif
cpufreq_unregister_driver(&centrino_driver); cpufreq_unregister_driver(&centrino_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>"); MODULE_AUTHOR ("Jeremy Fitzhardinge <jeremy@goop.org>");

View file

@ -48,10 +48,6 @@ config X86_SPEEDSTEP_CENTRINO
If in doubt, say N. If in doubt, say N.
config X86_SPEEDSTEP_CENTRINO_ACPI
bool
depends on X86_SPEEDSTEP_CENTRINO
config X86_ACPI_CPUFREQ config X86_ACPI_CPUFREQ
tristate "ACPI Processor P-States driver" tristate "ACPI Processor P-States driver"
select CPU_FREQ_TABLE select CPU_FREQ_TABLE
@ -73,7 +69,7 @@ comment "shared options"
config X86_ACPI_CPUFREQ_PROC_INTF config X86_ACPI_CPUFREQ_PROC_INTF
bool "/proc/acpi/processor/../performance interface (deprecated)" bool "/proc/acpi/processor/../performance interface (deprecated)"
depends on PROC_FS 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 help
This enables the deprecated /proc/acpi/processor/../performance This enables the deprecated /proc/acpi/processor/../performance
interface. While it is helpful for debugging, the generic, interface. While it is helpful for debugging, the generic,

View file

@ -39,6 +39,10 @@
*/ */
static struct cpufreq_driver *cpufreq_driver; static struct cpufreq_driver *cpufreq_driver;
static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; 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); 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.min = policy->cpuinfo.min_freq;
policy->user_policy.max = policy->cpuinfo.max_freq; policy->user_policy.max = policy->cpuinfo.max_freq;
policy->user_policy.governor = policy->governor;
#ifdef CONFIG_SMP #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) { for_each_cpu_mask(j, policy->cpus) {
if (cpu == j) if (cpu == j)
continue; continue;
@ -873,6 +885,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
/* set default policy */ /* set default policy */
ret = __cpufreq_set_policy(policy, &new_policy); ret = __cpufreq_set_policy(policy, &new_policy);
policy->user_policy.policy = policy->policy; policy->user_policy.policy = policy->policy;
policy->user_policy.governor = policy->governor;
unlock_policy_rwsem_write(cpu); unlock_policy_rwsem_write(cpu);
@ -969,6 +982,11 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev)
} }
#ifdef CONFIG_SMP #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, /* if we have other CPUs still registered, we need to unlink them,
* or else wait_for_completion below will lock up. Clean the * or else wait_for_completion below will lock up. Clean the
* cpufreq_cpu_data[] while holding the lock, and remove the sysfs * 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) if (j == cpu)
continue; continue;
dprintk("removing link for cpu %u\n", j); 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); cpu_sys_dev = get_cpu_sysdev(j);
sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq"); sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq");
cpufreq_cpu_put(data); cpufreq_cpu_put(data);
@ -1687,7 +1708,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
{ {
unsigned int cpu = (unsigned long)hcpu; unsigned int cpu = (unsigned long)hcpu;
struct sys_device *sys_dev; struct sys_device *sys_dev;
struct cpufreq_policy *policy;
sys_dev = get_cpu_sysdev(cpu); sys_dev = get_cpu_sysdev(cpu);
if (sys_dev) { if (sys_dev) {
@ -1701,11 +1721,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
if (unlikely(lock_policy_rwsem_write(cpu))) if (unlikely(lock_policy_rwsem_write(cpu)))
BUG(); BUG();
policy = cpufreq_cpu_data[cpu];
if (policy) {
__cpufreq_driver_target(policy, policy->min,
CPUFREQ_RELATION_H);
}
__cpufreq_remove_dev(sys_dev); __cpufreq_remove_dev(sys_dev);
break; break;
case CPU_DOWN_FAILED: case CPU_DOWN_FAILED: