diff options
-rw-r--r-- | xen/arch/x86/acpi/cpufreq/powernow.c | 30 | ||||
-rw-r--r-- | xen/drivers/acpi/pmstat.c | 4 | ||||
-rw-r--r-- | xen/drivers/cpufreq/utility.c | 35 | ||||
-rw-r--r-- | xen/include/acpi/cpufreq/cpufreq.h | 4 |
4 files changed, 55 insertions, 18 deletions
diff --git a/xen/arch/x86/acpi/cpufreq/powernow.c b/xen/arch/x86/acpi/cpufreq/powernow.c index 69d7f94a1e..48b7188b8a 100644 --- a/xen/arch/x86/acpi/cpufreq/powernow.c +++ b/xen/arch/x86/acpi/cpufreq/powernow.c @@ -68,16 +68,37 @@ static void transition_pstate(void *drvcmd) struct drv_cmd *cmd; cmd = (struct drv_cmd *) drvcmd; - if (cmd->turbo != CPUFREQ_TURBO_UNSUPPORTED) { + + wrmsrl(MSR_PSTATE_CTRL, cmd->val); +} + +static void update_cpb(void *data) +{ + struct cpufreq_policy *policy = (struct cpufreq_policy *)data; + + if (policy->turbo != CPUFREQ_TURBO_UNSUPPORTED) { uint64_t msr_content; + rdmsrl(MSR_K8_HWCR, msr_content); - if (cmd->turbo == CPUFREQ_TURBO_ENABLED) + + if (policy->turbo == CPUFREQ_TURBO_ENABLED) msr_content &= ~MSR_HWCR_CPBDIS_MASK; else msr_content |= MSR_HWCR_CPBDIS_MASK; + wrmsrl(MSR_K8_HWCR, msr_content); } - wrmsrl(MSR_PSTATE_CTRL, cmd->val); +} + +static int powernow_cpufreq_update (int cpuid, + struct cpufreq_policy *policy) +{ + if (!cpumask_test_cpu(cpuid, &cpu_online_map)) + return -EINVAL; + + on_selected_cpus(cpumask_of(cpuid), update_cpb, policy, 1); + + return 0; } static int powernow_cpufreq_target(struct cpufreq_policy *policy, @@ -300,7 +321,8 @@ static struct cpufreq_driver powernow_cpufreq_driver = { .verify = powernow_cpufreq_verify, .target = powernow_cpufreq_target, .init = powernow_cpufreq_cpu_init, - .exit = powernow_cpufreq_cpu_exit + .exit = powernow_cpufreq_cpu_exit, + .update = powernow_cpufreq_update }; unsigned int __init powernow_register_driver() diff --git a/xen/drivers/acpi/pmstat.c b/xen/drivers/acpi/pmstat.c index dbc1c44a61..8788f01f70 100644 --- a/xen/drivers/acpi/pmstat.c +++ b/xen/drivers/acpi/pmstat.c @@ -494,13 +494,13 @@ int do_pm_op(struct xen_sysctl_pm_op *op) case XEN_SYSCTL_pm_op_enable_turbo: { - cpufreq_enable_turbo(op->cpuid); + ret = cpufreq_update_turbo(op->cpuid, CPUFREQ_TURBO_ENABLED); break; } case XEN_SYSCTL_pm_op_disable_turbo: { - cpufreq_disable_turbo(op->cpuid); + ret = cpufreq_update_turbo(op->cpuid, CPUFREQ_TURBO_DISABLED); break; } diff --git a/xen/drivers/cpufreq/utility.c b/xen/drivers/cpufreq/utility.c index fad54651b3..3dd70e2716 100644 --- a/xen/drivers/cpufreq/utility.c +++ b/xen/drivers/cpufreq/utility.c @@ -390,24 +390,39 @@ int cpufreq_driver_getavg(unsigned int cpu, unsigned int flag) return policy->cur; } -void cpufreq_enable_turbo(int cpuid) +int cpufreq_update_turbo(int cpuid, int new_state) { struct cpufreq_policy *policy; + int curr_state; + int ret = 0; + + if (new_state != CPUFREQ_TURBO_ENABLED && + new_state != CPUFREQ_TURBO_DISABLED) + return -EINVAL; policy = per_cpu(cpufreq_cpu_policy, cpuid); - if (policy && policy->turbo != CPUFREQ_TURBO_UNSUPPORTED) - policy->turbo = CPUFREQ_TURBO_ENABLED; -} + if (!policy) + return -EACCES; -void cpufreq_disable_turbo(int cpuid) -{ - struct cpufreq_policy *policy; + if (policy->turbo == CPUFREQ_TURBO_UNSUPPORTED) + return -EOPNOTSUPP; - policy = per_cpu(cpufreq_cpu_policy, cpuid); - if (policy && policy->turbo != CPUFREQ_TURBO_UNSUPPORTED) - policy->turbo = CPUFREQ_TURBO_DISABLED; + curr_state = policy->turbo; + if (curr_state == new_state) + return 0; + + policy->turbo = new_state; + if (cpufreq_driver->update) + { + ret = cpufreq_driver->update(cpuid, policy); + if (ret) + policy->turbo = curr_state; + } + + return ret; } + int cpufreq_get_turbo_status(int cpuid) { struct cpufreq_policy *policy; diff --git a/xen/include/acpi/cpufreq/cpufreq.h b/xen/include/acpi/cpufreq/cpufreq.h index 1798b9bb19..f96c3e4ccf 100644 --- a/xen/include/acpi/cpufreq/cpufreq.h +++ b/xen/include/acpi/cpufreq/cpufreq.h @@ -124,8 +124,7 @@ extern int cpufreq_driver_getavg(unsigned int cpu, unsigned int flag); #define CPUFREQ_TURBO_UNSUPPORTED 0 #define CPUFREQ_TURBO_ENABLED 1 -extern void cpufreq_enable_turbo(int cpuid); -extern void cpufreq_disable_turbo(int cpuid); +extern int cpufreq_update_turbo(int cpuid, int new_state); extern int cpufreq_get_turbo_status(int cpuid); static __inline__ int @@ -146,6 +145,7 @@ struct cpufreq_driver { char name[CPUFREQ_NAME_LEN]; int (*init)(struct cpufreq_policy *policy); int (*verify)(struct cpufreq_policy *policy); + int (*update)(int cpuid, struct cpufreq_policy *policy); int (*target)(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation); |