aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/acpi/cpufreq/powernow.c30
-rw-r--r--xen/drivers/acpi/pmstat.c4
-rw-r--r--xen/drivers/cpufreq/utility.c35
-rw-r--r--xen/include/acpi/cpufreq/cpufreq.h4
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);