aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/acpi/cpufreq/powernow.c62
1 files changed, 25 insertions, 37 deletions
diff --git a/xen/arch/x86/acpi/cpufreq/powernow.c b/xen/arch/x86/acpi/cpufreq/powernow.c
index 48b7188b8a..a9b779237c 100644
--- a/xen/arch/x86/acpi/cpufreq/powernow.c
+++ b/xen/arch/x86/acpi/cpufreq/powernow.c
@@ -56,20 +56,9 @@
static struct cpufreq_driver powernow_cpufreq_driver;
-struct drv_cmd {
- unsigned int type;
- const cpumask_t *mask;
- u32 val;
- int turbo;
-};
-
-static void transition_pstate(void *drvcmd)
+static void transition_pstate(void *pstate)
{
- struct drv_cmd *cmd;
- cmd = (struct drv_cmd *) drvcmd;
-
-
- wrmsrl(MSR_PSTATE_CTRL, cmd->val);
+ wrmsrl(MSR_PSTATE_CTRL, *(unsigned int *)pstate);
}
static void update_cpb(void *data)
@@ -106,13 +95,9 @@ static int powernow_cpufreq_target(struct cpufreq_policy *policy,
{
struct acpi_cpufreq_data *data = cpufreq_drv_data[policy->cpu];
struct processor_performance *perf;
- struct cpufreq_freqs freqs;
- cpumask_t online_policy_cpus;
- struct drv_cmd cmd;
- unsigned int next_state = 0; /* Index into freq_table */
- unsigned int next_perf_state = 0; /* Index into perf table */
- int result = 0;
- int j = 0;
+ unsigned int next_state; /* Index into freq_table */
+ unsigned int next_perf_state; /* Index into perf table */
+ int result;
if (unlikely(data == NULL ||
data->acpi_data == NULL || data->freq_table == NULL)) {
@@ -125,9 +110,7 @@ static int powernow_cpufreq_target(struct cpufreq_policy *policy,
target_freq,
relation, &next_state);
if (unlikely(result))
- return -ENODEV;
-
- cpumask_and(&online_policy_cpus, policy->cpus, &cpu_online_map);
+ return result;
next_perf_state = data->freq_table[next_state].index;
if (perf->state == next_perf_state) {
@@ -137,26 +120,31 @@ static int powernow_cpufreq_target(struct cpufreq_policy *policy,
return 0;
}
- if (policy->shared_type != CPUFREQ_SHARED_TYPE_ANY)
- cmd.mask = &online_policy_cpus;
- else
- cmd.mask = cpumask_of(policy->cpu);
-
- freqs.old = perf->states[perf->state].core_frequency * 1000;
- freqs.new = data->freq_table[next_state].frequency;
+ if (policy->shared_type == CPUFREQ_SHARED_TYPE_HW &&
+ likely(policy->cpu == smp_processor_id())) {
+ transition_pstate(&next_perf_state);
+ cpufreq_statistic_update(policy->cpu, perf->state, next_perf_state);
+ } else {
+ cpumask_t online_policy_cpus;
+ unsigned int cpu;
- cmd.val = next_perf_state;
- cmd.turbo = policy->turbo;
+ cpumask_and(&online_policy_cpus, policy->cpus, &cpu_online_map);
- on_selected_cpus(cmd.mask, transition_pstate, &cmd, 1);
+ if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
+ unlikely(policy->cpu != smp_processor_id()))
+ on_selected_cpus(&online_policy_cpus, transition_pstate,
+ &next_perf_state, 1);
+ else
+ transition_pstate(&next_perf_state);
- for_each_cpu(j, &online_policy_cpus)
- cpufreq_statistic_update(j, perf->state, next_perf_state);
+ for_each_cpu(cpu, &online_policy_cpus)
+ cpufreq_statistic_update(cpu, perf->state, next_perf_state);
+ }
perf->state = next_perf_state;
- policy->cur = freqs.new;
+ policy->cur = data->freq_table[next_state].frequency;
- return result;
+ return 0;
}
static int powernow_cpufreq_verify(struct cpufreq_policy *policy)