WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [IA64] Add cpufreq ia64 driver

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [IA64] Add cpufreq ia64 driver
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 10 Oct 2008 20:00:48 -0700
Delivery-date: Fri, 10 Oct 2008 20:02:51 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
# Date 1223605044 -32400
# Node ID a311996570f4d81a954766d2638e64b7cd78489a
# Parent  e02974a9587225c589cf59a81d900cdf2a221a28
[IA64] Add cpufreq ia64 driver

For IA64 Platform, add cpufreq driver for ia64 cpu, implementing
cpufreq_driver->init()/ exit()/ verify()/ target()/ get()

Signed-off-by: Yu, Ke <ke.yu@xxxxxxxxx>
Signed-off-by: Liu, Jinsong <jinsong.liu@xxxxxxxxx>
---
 xen/arch/ia64/xen/cpufreq/cpufreq.c |  309 +++++++++++++++++++++++++++++++++++-
 1 files changed, 306 insertions(+), 3 deletions(-)

diff -r e02974a95872 -r a311996570f4 xen/arch/ia64/xen/cpufreq/cpufreq.c
--- a/xen/arch/ia64/xen/cpufreq/cpufreq.c       Fri Oct 03 12:50:28 2008 +0900
+++ b/xen/arch/ia64/xen/cpufreq/cpufreq.c       Fri Oct 10 11:17:24 2008 +0900
@@ -1,8 +1,311 @@
-
+/*
+ * arch/ia64/kernel/cpufreq/acpi-cpufreq.c
+ * This file provides the ACPI based P-state support. This
+ * module works with generic cpufreq infrastructure. Most of
+ * the code is based on i386 version
+ * (arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c)
+ *
+ * Copyright (C) 2005 Intel Corp
+ *      Venkatesh Pallipadi <venkatesh.pallipadi@xxxxxxxxx>
+ *
+ * Sep 2008 - Liu Jinsong <jinsong.liu@xxxxxxxxx>
+ *      porting IPF acpi-cpufreq.c from Linux 2.6.23 to Xen hypervisor
+ */
+
+#include <xen/types.h>
 #include <xen/errno.h>
+#include <xen/delay.h>
+#include <xen/cpumask.h>
+#include <xen/sched.h>
+#include <xen/timer.h>
+#include <xen/xmalloc.h>
+#include <asm/bug.h>
+#include <asm/io.h>
+#include <asm/config.h>
+#include <asm/processor.h>
+#include <asm/percpu.h>
+#include <asm/pal.h>
 #include <acpi/acpi.h>
-#include <acpi/cpufreq/processor_perf.h>
-#include <public/platform.h>
+#include <acpi/cpufreq/cpufreq.h>
+
+static struct acpi_cpufreq_data *drv_data[NR_CPUS];
+
+static struct cpufreq_driver acpi_cpufreq_driver;
+
+static int
+processor_get_pstate (u32 *value)
+{
+       u64 pstate_index = 0;
+       s64 retval;
+
+       retval = ia64_pal_get_pstate(&pstate_index,
+                       PAL_GET_PSTATE_TYPE_INSTANT);
+       *value = (u32) pstate_index;
+
+       if (retval)
+               printk("Failed to get current freq\n");
+
+       return (int)retval;
+}
+
+static unsigned int
+extract_clock (unsigned value)
+{
+       unsigned long i;
+       unsigned int cpu;
+       struct processor_performance *perf;
+
+       cpu = smp_processor_id();
+       perf = &processor_pminfo[cpu]->perf;
+
+       for (i = 0; i < perf->state_count; i++) {
+               if (value == perf->states[i].status)
+                       return perf->states[i].core_frequency;
+       }
+       return perf->states[i-1].core_frequency;
+}
+
+static void
+processor_get_freq (void *data)
+{
+       unsigned int *freq = data;
+       int ret = 0;
+       u32 value = 0;
+       unsigned int clock_freq;
+
+       ret = processor_get_pstate(&value);
+       if (ret) {
+               *freq = 0;
+               return;
+       }
+
+       clock_freq = extract_clock(value);
+       *freq = (clock_freq*1000);
+       return;
+}
+
+static unsigned int
+acpi_cpufreq_get (unsigned int cpu)
+{
+       unsigned int freq;
+
+       if (!cpu_online(cpu))
+               return 0;
+
+       if (cpu == smp_processor_id())
+               processor_get_freq((void*)&freq);
+       else
+               smp_call_function_single(cpu, processor_get_freq,
+                                        (void *)&freq, 0, 1);
+
+       return freq;
+}
+
+static void
+processor_set_pstate (void *data)
+{
+       u32 *value = data;
+       s64 retval;
+
+       retval = ia64_pal_set_pstate((u64)*value);
+
+       if (retval)
+               *value = 1;
+       else
+               *value = 0;
+}
+
+static int
+processor_set_freq (struct acpi_cpufreq_data *data,
+               struct cpufreq_policy *policy, int state)
+{
+       u32 value = 0;
+       unsigned int cpu = policy->cpu;
+
+       if (!cpu_online(cpu))
+               return -ENODEV;
+
+       if (state == data->acpi_data->state) {
+               if (unlikely(policy->resume)) {
+                       printk(KERN_INFO
+                              "Called after resume, resetting to P%d\n",
+                              state);
+                       policy->resume = 0;
+               } else {
+                       printk(KERN_DEBUG"Already at target state (P%d)\n",
+                              state);
+                       return 0;
+               }
+       }
+
+       value = (u32) data->acpi_data->states[state].control;
+
+       if (cpu == smp_processor_id())
+               processor_set_pstate((void *)&value);
+       else
+               smp_call_function_single(cpu, processor_set_pstate,
+                               (void *)&value, 0, 1);
+
+       if (value) {
+               printk(KERN_WARNING "Transition failed\n");
+               return -ENODEV;
+       }
+
+       cpufreq_statistic_update(cpu, data->acpi_data->state, state);
+
+       data->acpi_data->state = state;
+
+       return 0;
+}
+
+static int
+acpi_cpufreq_target (struct cpufreq_policy *policy,
+               unsigned int target_freq, unsigned int relation)
+{
+       struct acpi_cpufreq_data *data = drv_data[policy->cpu];
+       unsigned int next_state = 0;
+       unsigned int result = 0;
+
+       result = cpufreq_frequency_table_target(policy,
+                       data->freq_table, target_freq, relation, &next_state);
+       if (result)
+               return (result);
+
+       result = processor_set_freq(data, policy, next_state);
+
+       return (result);
+}
+
+static int
+acpi_cpufreq_verify (struct cpufreq_policy *policy)
+{
+       struct acpi_cpufreq_data *data = drv_data[policy->cpu];
+       struct processor_performance *perf =
+               &processor_pminfo[policy->cpu]->perf;
+
+       if (!policy || !data)
+               return -EINVAL;
+
+       cpufreq_verify_within_limits(policy, 0,
+                       perf->states[perf->platform_limit].core_frequency * 
1000);
+
+       return cpufreq_frequency_table_verify(policy, data->freq_table);
+}
+
+static int
+acpi_cpufreq_cpu_init (struct cpufreq_policy *policy)
+{
+       unsigned int i;
+       unsigned int cpu = policy->cpu;
+       unsigned int result = 0;
+       struct acpi_cpufreq_data *data;
+
+       data = xmalloc(struct acpi_cpufreq_data);
+       if (!data)
+               return -ENOMEM;
+       memset(data, 0, sizeof(struct acpi_cpufreq_data));
+
+       drv_data[cpu] = data;
+
+       data->acpi_data = &processor_pminfo[cpu]->perf;
+
+       /* capability check */
+       if (data->acpi_data->state_count <= 1) {
+               printk(KERN_WARNING "P-States\n");
+               result = -ENODEV;
+               goto err_unreg;
+       }
+
+       if ((data->acpi_data->control_register.space_id !=
+                               ACPI_ADR_SPACE_FIXED_HARDWARE) ||
+                       (data->acpi_data->status_register.space_id !=
+                        ACPI_ADR_SPACE_FIXED_HARDWARE)) {
+               result = -ENODEV;
+               goto err_unreg;
+       }
+
+       data->freq_table = xmalloc_array(struct cpufreq_frequency_table,
+                       (data->acpi_data->state_count + 1));
+       if (!data->freq_table) {
+               result = -ENOMEM;
+               goto err_unreg;
+       }
+
+       /* detect transition latency */
+       policy->cpuinfo.transition_latency = 0;
+       for (i=0; i<data->acpi_data->state_count; i++) {
+               if ((data->acpi_data->states[i].transition_latency * 1000) >
+                               policy->cpuinfo.transition_latency) {
+                       policy->cpuinfo.transition_latency =
+                               data->acpi_data->states[i].transition_latency * 
1000;
+               }
+       }
+       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+       policy->cur = acpi_cpufreq_get(policy->cpu);
+       printk(KERN_INFO "Current freq of CPU %u is %u\n", cpu, policy->cur);
+
+       /* table init */
+       for (i = 0; i <= data->acpi_data->state_count; i++) {
+               data->freq_table[i].index = i;
+               if (i < data->acpi_data->state_count) {
+                       data->freq_table[i].frequency =
+                               data->acpi_data->states[i].core_frequency * 
1000;
+               } else {
+                       data->freq_table[i].frequency = CPUFREQ_TABLE_END;
+               }
+       }
+
+       result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
+       if (result)
+               goto err_freqfree;
+
+       data->acpi_data->state = 0;
+       policy->resume = 1;
+
+       return result;
+
+err_freqfree:
+       xfree(data->freq_table);
+err_unreg:
+       xfree(data);
+       drv_data[cpu] = NULL;
+
+       return result;
+}
+
+static int
+acpi_cpufreq_cpu_exit (struct cpufreq_policy *policy)
+{
+       struct acpi_cpufreq_data *data = drv_data[policy->cpu];
+
+       if (data) {
+               drv_data[policy->cpu] = NULL;
+               xfree(data->freq_table);
+               xfree(data);
+       }
+
+       return 0;
+}
+
+static struct cpufreq_driver acpi_cpufreq_driver = {
+       .verify     = acpi_cpufreq_verify,
+       .target     = acpi_cpufreq_target,
+       .get        = acpi_cpufreq_get,
+       .init       = acpi_cpufreq_cpu_init,
+       .exit       = acpi_cpufreq_cpu_exit,
+};
+
+static int __init cpufreq_driver_init(void)
+{
+       int ret = 0;
+
+       if (cpufreq_controller == FREQCTL_xen)
+               ret = cpufreq_register_driver(&acpi_cpufreq_driver);
+
+       return ret;
+}
+__initcall(cpufreq_driver_init);
 
 int get_cpu_id(u8 acpi_id)
 {

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [IA64] Add cpufreq ia64 driver, Xen patchbot-unstable <=