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] x86: Clean up cpufreq core logic

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86: Clean up cpufreq core logic
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 16 Sep 2008 06:01:01 -0700
Delivery-date: Tue, 16 Sep 2008 06:02:50 -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 Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1221212090 -3600
# Node ID f125e481d8b65b81dd794d60a99fb0b823eaee2c
# Parent  346c073ed6a4f0debca36588039d649e2efd93c3
x86: Clean up cpufreq core logic

Clean up cpufreq core logic, which now can cope with cpu
online/offline event, and also dynamic platform limitation event
(_PPC).

Signed-off-by: Liu, Jinsong <jinsong.liu@xxxxxxxxx>
---
 xen/arch/x86/acpi/cpufreq/cpufreq.c          |  287 ++++++++++++++++-----------
 xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c |    7 
 xen/arch/x86/acpi/cpufreq/powernow.c         |   10 
 xen/arch/x86/acpi/cpufreq/utility.c          |  186 ++++++++---------
 xen/arch/x86/acpi/pmstat.c                   |    2 
 xen/arch/x86/acpi/power.c                    |    6 
 xen/arch/x86/platform_hypercall.c            |   39 ++-
 xen/arch/x86/smpboot.c                       |    5 
 xen/include/acpi/cpufreq/cpufreq.h           |   74 ++++++
 xen/include/acpi/cpufreq/processor_perf.h    |   19 -
 xen/include/public/platform.h                |    2 
 11 files changed, 391 insertions(+), 246 deletions(-)

diff -r 346c073ed6a4 -r f125e481d8b6 xen/arch/x86/acpi/cpufreq/cpufreq.c
--- a/xen/arch/x86/acpi/cpufreq/cpufreq.c       Thu Sep 11 18:00:06 2008 +0100
+++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c       Fri Sep 12 10:34:50 2008 +0100
@@ -32,6 +32,7 @@
 #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>
@@ -44,12 +45,8 @@
 #include <acpi/acpi.h>
 #include <acpi/cpufreq/cpufreq.h>
 
-struct processor_pminfo processor_pminfo[NR_CPUS];
-struct cpufreq_policy xen_px_policy[NR_CPUS];
-
-static cpumask_t *cpufreq_dom_pt;
-static unsigned long *cpufreq_dom_mask;
-static unsigned int cpufreq_dom_max;
+/* TODO: change to link list later as domain number may be sparse */
+static cpumask_t cpufreq_dom_map[NR_CPUS];
 
 enum {
     UNDEFINED_CAPABLE = 0,
@@ -335,7 +332,7 @@ static int acpi_cpufreq_target(struct cp
     if (unlikely(result))
         return -ENODEV;
 
-    online_policy_cpus = policy->cpus;
+    cpus_and(online_policy_cpus, cpu_online_map, policy->cpus);
 
     next_perf_state = data->freq_table[next_state].index;
     if (perf->state == next_perf_state) {
@@ -388,6 +385,20 @@ static int acpi_cpufreq_target(struct cp
     policy->cur = freqs.new;
 
     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 unsigned long
@@ -441,14 +452,6 @@ acpi_cpufreq_cpu_init(struct cpufreq_pol
     perf = data->acpi_data;
     policy->shared_type = perf->shared_type;
 
-    /* 
-     * Currently the latest linux (kernel version 2.6.26) 
-     * still has issue when handle the situation _psd HW_ALL coordination.
-     * In Xen hypervisor, we handle _psd HW_ALL coordination in same way as
-     * _psd SW_ALL coordination for the seek of safety.
-     */
-    policy->cpus = perf->shared_cpu_map;
-
     /* capability check */
     if (perf->state_count <= 1) {
         printk("No P-States\n");
@@ -496,6 +499,7 @@ acpi_cpufreq_cpu_init(struct cpufreq_pol
             policy->cpuinfo.transition_latency =
                 perf->states[i].transition_latency * 1000;
     }
+    policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 
     data->max_freq = perf->states[0].core_frequency * 1000;
     /* table init */
@@ -554,114 +558,173 @@ err_unreg:
     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,
     .init   = acpi_cpufreq_cpu_init,
+    .exit   = acpi_cpufreq_cpu_exit,
 };
 
-void cpufreq_dom_exit(void)
-{
-    cpufreq_dom_max = 0;
-    if (cpufreq_dom_mask)
-        xfree(cpufreq_dom_mask);
-    if (cpufreq_dom_pt)
-        xfree(cpufreq_dom_pt);
-}
-
-int cpufreq_dom_init(void)
-{
-    unsigned int i;
-
-    cpufreq_dom_max = 0;
-
-    for_each_online_cpu(i) {
-        if (cpufreq_dom_max < processor_pminfo[i].perf.domain_info.domain)
-            cpufreq_dom_max = processor_pminfo[i].perf.domain_info.domain;
-    }
-    cpufreq_dom_max++;
-
-    cpufreq_dom_mask = xmalloc_array(unsigned long,
-                                     BITS_TO_LONGS(cpufreq_dom_max));
-    if (!cpufreq_dom_mask)
-        return -ENOMEM;
-    bitmap_zero(cpufreq_dom_mask, cpufreq_dom_max);
-
-    cpufreq_dom_pt = xmalloc_array(cpumask_t, cpufreq_dom_max);
-    if (!cpufreq_dom_pt)
-        return -ENOMEM;
-    memset(cpufreq_dom_pt, 0, cpufreq_dom_max * sizeof(cpumask_t));
-
-    for_each_online_cpu(i) {
-        __set_bit(processor_pminfo[i].perf.domain_info.domain, 
cpufreq_dom_mask);
-        cpu_set(i, 
cpufreq_dom_pt[processor_pminfo[i].perf.domain_info.domain]);
-    }
-
-    for_each_online_cpu(i)
-        processor_pminfo[i].perf.shared_cpu_map =
-            cpufreq_dom_pt[processor_pminfo[i].perf.domain_info.domain];
+int cpufreq_limit_change(unsigned int cpu)
+{
+    struct processor_performance *perf = &processor_pminfo[cpu].perf;
+    struct cpufreq_policy *data = cpufreq_cpu_policy[cpu];
+    struct cpufreq_policy policy;
+
+    if (!cpu_online(cpu) || !data)
+        return -ENODEV;
+
+    if ((perf->platform_limit < 0) || 
+        (perf->platform_limit >= perf->state_count))
+        return -EINVAL;
+
+    memcpy(&policy, data, sizeof(struct cpufreq_policy)); 
+
+    policy.max =
+        perf->states[perf->platform_limit].core_frequency * 1000;
+
+    return __cpufreq_set_policy(data, &policy);
+}
+
+int cpufreq_add_cpu(unsigned int cpu)
+{
+    int ret = 0;
+    unsigned int firstcpu;
+    unsigned int dom;
+    unsigned int j;
+    struct cpufreq_policy new_policy;
+    struct cpufreq_policy *policy;
+    struct processor_performance *perf = &processor_pminfo[cpu].perf;
+
+    /* to protect the case when Px was not controlled by xen */
+    if (!(perf->init & XEN_PX_INIT))
+        return 0;
+
+    if (cpu_is_offline(cpu) || cpufreq_cpu_policy[cpu])
+        return -EINVAL;
+
+    ret = px_statistic_init(cpu);
+    if (ret)
+        return ret;
+
+    dom = perf->domain_info.domain;
+    if (cpus_weight(cpufreq_dom_map[dom])) {
+        /* share policy with the first cpu since on same boat */
+        firstcpu = first_cpu(cpufreq_dom_map[dom]);
+        policy = cpufreq_cpu_policy[firstcpu];
+
+        cpufreq_cpu_policy[cpu] = policy;
+        cpu_set(cpu, cpufreq_dom_map[dom]);
+        cpu_set(cpu, policy->cpus);
+
+        printk(KERN_EMERG"adding CPU %u\n", cpu);
+    } else {
+        /* for the first cpu, setup policy and do init work */
+        policy = xmalloc(struct cpufreq_policy);
+        if (!policy) {
+            px_statistic_exit(cpu);
+            return -ENOMEM;
+        }
+        memset(policy, 0, sizeof(struct cpufreq_policy));
+
+        cpufreq_cpu_policy[cpu] = policy;
+        cpu_set(cpu, cpufreq_dom_map[dom]);
+        cpu_set(cpu, policy->cpus);
+
+        policy->cpu = cpu;
+        ret = cpufreq_driver->init(policy);
+        if (ret)
+            goto err1;
+        printk(KERN_EMERG"CPU %u initialization completed\n", cpu);
+    }
+
+    /*
+     * After get full cpumap of the coordination domain,
+     * we can safely start gov here.
+     */
+    if (cpus_weight(cpufreq_dom_map[dom]) ==
+        perf->domain_info.num_processors) {
+        memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
+        policy->governor = NULL;
+        ret = __cpufreq_set_policy(policy, &new_policy);
+        if (ret)
+            goto err2;
+    }
 
     return 0;
-}
-
-static int cpufreq_cpu_init(void)
-{
-    int i, ret = 0;
-
-    for_each_online_cpu(i) {
-        xen_px_policy[i].cpu = i;
-
-        ret = px_statistic_init(i);
-        if (ret)
-            return ret;
-
-        ret = acpi_cpufreq_cpu_init(&xen_px_policy[i]);
-        if (ret)
-            return ret;
-    }
+
+err2:
+    cpufreq_driver->exit(policy);
+err1:
+    for_each_cpu_mask(j, cpufreq_dom_map[dom]) {
+        cpufreq_cpu_policy[j] = NULL;
+        px_statistic_exit(j);
+    }
+
+    cpus_clear(cpufreq_dom_map[dom]);
+    xfree(policy);
     return ret;
 }
 
-int cpufreq_dom_dbs(unsigned int event)
-{
-    unsigned int cpu, dom;
+int cpufreq_del_cpu(unsigned int cpu)
+{
+    unsigned int dom;
+    struct cpufreq_policy *policy;
+    struct processor_performance *perf = &processor_pminfo[cpu].perf;
+
+    /* to protect the case when Px was not controlled by xen */
+    if (!(perf->init & XEN_PX_INIT))
+        return 0;
+
+    if (cpu_is_offline(cpu) || !cpufreq_cpu_policy[cpu])
+        return -EINVAL;
+
+    dom = perf->domain_info.domain;
+    policy = cpufreq_cpu_policy[cpu];
+
+    printk(KERN_EMERG"deleting CPU %u\n", cpu);
+
+    /* for the first cpu of the domain, stop gov */
+    if (cpus_weight(cpufreq_dom_map[dom]) ==
+        perf->domain_info.num_processors)
+        __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+
+    cpufreq_cpu_policy[cpu] = NULL;
+    cpu_clear(cpu, policy->cpus);
+    cpu_clear(cpu, cpufreq_dom_map[dom]);
+    px_statistic_exit(cpu);
+
+    /* for the last cpu of the domain, clean room */
+    /* It's safe here to free freq_table, drv_data and policy */
+    if (!cpus_weight(cpufreq_dom_map[dom])) {
+        cpufreq_driver->exit(policy);
+        xfree(policy);
+    }
+
+    return 0;
+}
+
+static int __init cpufreq_driver_init(void)
+{
     int ret = 0;
 
-    for (dom = 0; dom < cpufreq_dom_max; dom++) {
-        if (!test_bit(dom, cpufreq_dom_mask))
-            continue;
-        cpu = first_cpu(cpufreq_dom_pt[dom]);
-        ret = cpufreq_governor_dbs(&xen_px_policy[cpu], event);
-        if (ret)
-            return ret;
-    }
+    if ((cpufreq_controller == FREQCTL_xen) &&
+        (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL))
+        ret = cpufreq_register_driver(&acpi_cpufreq_driver);
+
     return ret;
 }
-
-int acpi_cpufreq_init(void)
-{
-    int ret = 0;
-    
-    /* setup cpumask of psd dom and shared cpu map of cpu */
-    ret = cpufreq_dom_init();
-    if (ret)
-        goto err;
-
-    /* setup cpufreq driver */
-    cpufreq_driver = &acpi_cpufreq_driver;
-
-    /* setup cpufreq infrastructure */
-    ret = cpufreq_cpu_init();
-    if (ret)
-        goto err;
-
-    /* setup cpufreq dbs according to dom coordiation */
-    ret = cpufreq_dom_dbs(CPUFREQ_GOV_START);
-    if (ret)
-        goto err;
-
-    return ret;
-
-err:
-    cpufreq_dom_exit();
-    return ret;
-}
+__initcall(cpufreq_driver_init);
diff -r 346c073ed6a4 -r f125e481d8b6 
xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c
--- a/xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c      Thu Sep 11 18:00:06 
2008 +0100
+++ b/xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c      Fri Sep 12 10:34:50 
2008 +0100
@@ -238,4 +238,9 @@ int cpufreq_governor_dbs(struct cpufreq_
         break;
     }
     return 0;
-} 
+}
+
+struct cpufreq_governor cpufreq_gov_dbs = {
+    .name = "ondemand",
+    .governor = cpufreq_governor_dbs,
+};
diff -r 346c073ed6a4 -r f125e481d8b6 xen/arch/x86/acpi/cpufreq/powernow.c
--- a/xen/arch/x86/acpi/cpufreq/powernow.c      Thu Sep 11 18:00:06 2008 +0100
+++ b/xen/arch/x86/acpi/cpufreq/powernow.c      Fri Sep 12 10:34:50 2008 +0100
@@ -50,7 +50,7 @@
 #define MSR_PSTATE_CUR_LIMIT    0xc0010061 /* pstate current limit MSR */
 
 extern struct processor_pminfo processor_pminfo[NR_CPUS];
-extern struct cpufreq_policy xen_px_policy[NR_CPUS];
+extern struct cpufreq_policy *cpufreq_cpu_policy[NR_CPUS];
 
 struct powernow_cpufreq_data {
     struct processor_performance *acpi_data;
@@ -281,9 +281,9 @@ int powernow_cpufreq_init(void)
 
     /* setup cpufreq infrastructure */
     for_each_online_cpu(i) {
-        xen_px_policy[i].cpu = i;
-
-        ret = powernow_cpufreq_cpu_init(&xen_px_policy[i]);
+        cpufreq_cpu_policy[i]->cpu = i;
+
+        ret = powernow_cpufreq_cpu_init(cpufreq_cpu_policy[i]);
         if (ret)
             goto cpufreq_init_out;
     }
@@ -293,7 +293,7 @@ int powernow_cpufreq_init(void)
         if (!cpu_isset(dom, dom_mask))
             continue;
         i = first_cpu(pt[dom]);
-        ret = cpufreq_governor_dbs(&xen_px_policy[i], CPUFREQ_GOV_START);
+        ret = cpufreq_governor_dbs(cpufreq_cpu_policy[i], CPUFREQ_GOV_START);
         if (ret)
             goto cpufreq_init_out;
     }
diff -r 346c073ed6a4 -r f125e481d8b6 xen/arch/x86/acpi/cpufreq/utility.c
--- a/xen/arch/x86/acpi/cpufreq/utility.c       Thu Sep 11 18:00:06 2008 +0100
+++ b/xen/arch/x86/acpi/cpufreq/utility.c       Fri Sep 12 10:34:50 2008 +0100
@@ -31,46 +31,13 @@
 #include <acpi/cpufreq/cpufreq.h>
 #include <public/sysctl.h>
 
-struct cpufreq_driver *cpufreq_driver;
+struct cpufreq_driver   *cpufreq_driver;
+struct processor_pminfo processor_pminfo[NR_CPUS];
+struct cpufreq_policy   *cpufreq_cpu_policy[NR_CPUS];
 
 /*********************************************************************
  *                    Px STATISTIC INFO                              *
  *********************************************************************/
-
-void px_statistic_suspend(void)
-{
-    int cpu;
-    uint64_t now;
-
-    now = NOW();
-
-    for_each_online_cpu(cpu) {
-        struct pm_px *pxpt = &px_statistic_data[cpu];
-        uint64_t total_idle_ns;
-        uint64_t tmp_idle_ns;
-
-        total_idle_ns = get_cpu_idle_time(cpu);
-        tmp_idle_ns = total_idle_ns - pxpt->prev_idle_wall;
-
-        pxpt->u.pt[pxpt->u.cur].residency +=
-                    now - pxpt->prev_state_wall;
-        pxpt->u.pt[pxpt->u.cur].residency -= tmp_idle_ns;
-    }
-}
-
-void px_statistic_resume(void)
-{
-    int cpu;
-    uint64_t now;
-
-    now = NOW();
-
-    for_each_online_cpu(cpu) {
-        struct pm_px *pxpt = &px_statistic_data[cpu];
-        pxpt->prev_state_wall = now;
-        pxpt->prev_idle_wall = get_cpu_idle_time(cpu);
-    }
-}
 
 void px_statistic_update(cpumask_t cpumask, uint8_t from, uint8_t to)
 {
@@ -101,7 +68,7 @@ void px_statistic_update(cpumask_t cpuma
     }
 }
 
-int px_statistic_init(int cpuid)
+int px_statistic_init(unsigned int cpuid)
 {
     uint32_t i, count;
     struct pm_px *pxpt = &px_statistic_data[cpuid];
@@ -123,7 +90,7 @@ int px_statistic_init(int cpuid)
     memset(pxpt->u.pt, 0, count * (sizeof(struct pm_px_val)));
 
     pxpt->u.total = pmpt->perf.state_count;
-    pxpt->u.usable = pmpt->perf.state_count - pmpt->perf.ppc;
+    pxpt->u.usable = pmpt->perf.state_count - pmpt->perf.platform_limit;
 
     for (i=0; i < pmpt->perf.state_count; i++)
         pxpt->u.pt[i].freq = pmpt->perf.states[i].core_frequency;
@@ -134,7 +101,16 @@ int px_statistic_init(int cpuid)
     return 0;
 }
 
-void px_statistic_reset(int cpuid)
+void px_statistic_exit(unsigned int cpuid)
+{
+    struct pm_px *pxpt = &px_statistic_data[cpuid];
+
+    xfree(pxpt->u.trans_pt);
+    xfree(pxpt->u.pt);
+    memset(pxpt, 0, sizeof(struct pm_px));
+}
+
+void px_statistic_reset(unsigned int cpuid)
 {
     uint32_t i, j, count;
     struct pm_px *pxpt = &px_statistic_data[cpuid];
@@ -182,6 +158,38 @@ int cpufreq_frequency_table_cpuinfo(stru
         return -EINVAL;
     else
         return 0;
+}
+
+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
+                                   struct cpufreq_frequency_table *table)
+{
+    unsigned int next_larger = ~0;
+    unsigned int i;
+    unsigned int count = 0;
+
+    if (!cpu_online(policy->cpu))
+        return -EINVAL;
+
+    cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+                                 policy->cpuinfo.max_freq);
+
+    for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+        unsigned int freq = table[i].frequency;
+        if (freq == CPUFREQ_ENTRY_INVALID)
+            continue;
+        if ((freq >= policy->min) && (freq <= policy->max))
+            count++;
+        else if ((next_larger > freq) && (freq > policy->max))
+            next_larger = freq;
+    }
+
+    if (!count)
+        policy->max = next_larger;
+
+    cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+                                 policy->cpuinfo.max_freq);
+
+    return 0;
 }
 
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
@@ -289,57 +297,51 @@ int __cpufreq_driver_getavg(struct cpufr
 
 
 /*********************************************************************
- *               CPUFREQ SUSPEND/RESUME                              *
- *********************************************************************/
-
-void cpufreq_suspend(void)
-{
-    int cpu;
-
-    /* to protect the case when Px was not controlled by xen */
-    for_each_online_cpu(cpu) {
-        struct processor_performance *perf = &processor_pminfo[cpu].perf;
-
-        if (!(perf->init & XEN_PX_INIT))
-            return;
-    }
-
-    cpufreq_dom_dbs(CPUFREQ_GOV_STOP);
-
-    cpufreq_dom_exit();
-
-    px_statistic_suspend();
-}
-
-int cpufreq_resume(void)
-{
-    int cpu, ret = 0;
-
-    /* 1. to protect the case when Px was not controlled by xen */
-    /* 2. set state and resume flag to sync cpu to right state and freq */
-    for_each_online_cpu(cpu) {
-        struct processor_performance *perf = &processor_pminfo[cpu].perf;
-        struct cpufreq_policy *policy = &xen_px_policy[cpu];
-
-        if (!(perf->init & XEN_PX_INIT))
-            goto err;
-        perf->state = 0;
-        policy->resume = 1;
-    }
-
-    px_statistic_resume();
-
-    ret = cpufreq_dom_init();
+ *                 POLICY                                            *
+ *********************************************************************/
+
+/*
+ * data   : current policy.
+ * policy : policy to be set.
+ */
+int __cpufreq_set_policy(struct cpufreq_policy *data,
+                                struct cpufreq_policy *policy)
+{
+    int ret = 0;
+
+    memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo));
+
+    if (policy->min > data->min && policy->min > policy->max)
+        return -EINVAL;
+
+    /* verify the cpu speed can be set within this limit */
+    ret = cpufreq_driver->verify(policy);
     if (ret)
-        goto err;
-
-    ret = cpufreq_dom_dbs(CPUFREQ_GOV_START);
-    if (ret)
-        goto err;
-
-    return ret;
-
-err:
-    cpufreq_dom_exit();
-    return ret;
-}
+        return ret;
+
+    data->min = policy->min;
+    data->max = policy->max;
+
+    if (policy->governor != data->governor) {
+        /* save old, working values */
+        struct cpufreq_governor *old_gov = data->governor;
+
+        /* end old governor */
+        if (data->governor)
+            __cpufreq_governor(data, CPUFREQ_GOV_STOP);
+
+        /* start new governor */
+        data->governor = policy->governor;
+        if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
+            /* new governor failed, so re-start old one */
+            if (old_gov) {
+                data->governor = old_gov;
+                __cpufreq_governor(data, CPUFREQ_GOV_START);
+            }
+            return -EINVAL;
+        }
+        /* might be a policy change, too, so fall through */
+    }
+
+    return __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
+}
diff -r 346c073ed6a4 -r f125e481d8b6 xen/arch/x86/acpi/pmstat.c
--- a/xen/arch/x86/acpi/pmstat.c        Thu Sep 11 18:00:06 2008 +0100
+++ b/xen/arch/x86/acpi/pmstat.c        Fri Sep 12 10:34:50 2008 +0100
@@ -78,7 +78,7 @@ int do_get_pm_info(struct xen_sysctl_get
         tmp_idle_ns = total_idle_ns - pxpt->prev_idle_wall;
 
         now = NOW();
-        pxpt->u.usable = pmpt->perf.state_count - pmpt->perf.ppc;
+        pxpt->u.usable = pmpt->perf.state_count - pmpt->perf.platform_limit;
         pxpt->u.pt[pxpt->u.cur].residency += now - pxpt->prev_state_wall;
         pxpt->u.pt[pxpt->u.cur].residency -= tmp_idle_ns;
         pxpt->prev_state_wall = now;
diff -r 346c073ed6a4 -r f125e481d8b6 xen/arch/x86/acpi/power.c
--- a/xen/arch/x86/acpi/power.c Thu Sep 11 18:00:06 2008 +0100
+++ b/xen/arch/x86/acpi/power.c Fri Sep 12 10:34:50 2008 +0100
@@ -133,14 +133,14 @@ static int enter_state(u32 state)
 
     freeze_domains();
 
-    cpufreq_suspend();
-
     disable_nonboot_cpus();
     if ( num_online_cpus() != 1 )
     {
         error = -EBUSY;
         goto enable_cpu;
     }
+
+    cpufreq_del_cpu(0);
 
     hvm_cpu_down();
 
@@ -189,8 +189,8 @@ static int enter_state(u32 state)
         BUG();
 
  enable_cpu:
+    cpufreq_add_cpu(0);
     enable_nonboot_cpus();
-    cpufreq_resume();
     thaw_domains();
     spin_unlock(&pm_lock);
     return error;
diff -r 346c073ed6a4 -r f125e481d8b6 xen/arch/x86/platform_hypercall.c
--- a/xen/arch/x86/platform_hypercall.c Thu Sep 11 18:00:06 2008 +0100
+++ b/xen/arch/x86/platform_hypercall.c Fri Sep 12 10:34:50 2008 +0100
@@ -393,7 +393,6 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
                 memcpy ((void *)&pxpt->status_register,
                     (void *)&xenpxpt->status_register,
                     sizeof(struct xen_pct_register));
-                pxpt->init |= XEN_PX_PCT;
             }
             if ( xenpxpt->flags & XEN_PX_PSS ) 
             {
@@ -411,7 +410,6 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
                     break;
                 }
                 pxpt->state_count = xenpxpt->state_count;
-                pxpt->init |= XEN_PX_PSS;
             }
             if ( xenpxpt->flags & XEN_PX_PSD )
             {
@@ -419,27 +417,34 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
                 memcpy ((void *)&pxpt->domain_info,
                     (void *)&xenpxpt->domain_info,
                     sizeof(struct xen_psd_package));
-                pxpt->init |= XEN_PX_PSD;
             }
             if ( xenpxpt->flags & XEN_PX_PPC )
             {
-                pxpt->ppc = xenpxpt->ppc;
-                pxpt->init |= XEN_PX_PPC;
-            }
-
-            if ( pxpt->init == ( XEN_PX_PCT | XEN_PX_PSS |
-                                 XEN_PX_PSD | XEN_PX_PPC ) )
-            {
-                pxpt->init |= XEN_PX_INIT;
+                pxpt->platform_limit = xenpxpt->platform_limit;
+
+                if ( pxpt->init == XEN_PX_INIT )
+                {
+                    ret = cpufreq_limit_change(cpuid);
+                    break;
+                }
+            }
+
+            if ( xenpxpt->flags == ( XEN_PX_PCT | XEN_PX_PSS |
+                                     XEN_PX_PSD | XEN_PX_PPC ) )
+            {
+                pxpt->init = XEN_PX_INIT;
                 cpu_count++;
-            }
-            if ( cpu_count == num_online_cpus() )
-            {
-                if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
+
+                /* Currently we only handle Intel and AMD processor */
+                if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+                    ret = cpufreq_add_cpu(cpuid);
+                else if ( (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
+                    (cpu_count == num_online_cpus()) )
                     ret = powernow_cpufreq_init();
                 else
-                    ret = acpi_cpufreq_init();
-            }
+                    break;
+            }
+
             break;
         }
  
diff -r 346c073ed6a4 -r f125e481d8b6 xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c    Thu Sep 11 18:00:06 2008 +0100
+++ b/xen/arch/x86/smpboot.c    Fri Sep 12 10:34:50 2008 +0100
@@ -55,6 +55,7 @@
 #include <mach_wakecpu.h>
 #include <smpboot_hooks.h>
 #include <xen/stop_machine.h>
+#include <acpi/cpufreq/processor_perf.h>
 
 #define set_kernel_exec(x, y) (0)
 #define setup_trampoline()    (bootsym_phys(trampoline_realmode_entry))
@@ -1232,6 +1233,8 @@ int __cpu_disable(void)
        mdelay(1);
        local_irq_disable();
 
+       cpufreq_del_cpu(cpu);
+
        time_suspend();
 
        remove_siblinginfo(cpu);
@@ -1421,6 +1424,8 @@ int __devinit __cpu_up(unsigned int cpu)
                mb();
                process_pending_timers();
        }
+
+       cpufreq_add_cpu(cpu);
        return 0;
 }
 
diff -r 346c073ed6a4 -r f125e481d8b6 xen/include/acpi/cpufreq/cpufreq.h
--- a/xen/include/acpi/cpufreq/cpufreq.h        Thu Sep 11 18:00:06 2008 +0100
+++ b/xen/include/acpi/cpufreq/cpufreq.h        Fri Sep 12 10:34:50 2008 +0100
@@ -18,6 +18,8 @@
 #include "processor_perf.h"
 
 #define CPUFREQ_NAME_LEN 16
+
+struct cpufreq_governor;
 
 struct cpufreq_cpuinfo {
     unsigned int        max_freq;
@@ -30,16 +32,21 @@ struct cpufreq_policy {
     unsigned int        shared_type;   /* ANY or ALL affected CPUs
                                           should set cpufreq */
     unsigned int        cpu;           /* cpu nr of registered CPU */
-    struct cpufreq_cpuinfo    cpuinfo; /* see above */
+    struct cpufreq_cpuinfo    cpuinfo;
 
     unsigned int        min;    /* in kHz */
     unsigned int        max;    /* in kHz */
     unsigned int        cur;    /* in kHz, only needed if cpufreq
                                  * governors are used */
+    struct cpufreq_governor     *governor;
+
     unsigned int        resume; /* flag for cpufreq 1st run
                                  * S3 wakeup, hotplug cpu, etc */
 };
-extern struct cpufreq_policy xen_px_policy[NR_CPUS];
+extern struct cpufreq_policy *cpufreq_cpu_policy[NR_CPUS];
+
+extern int __cpufreq_set_policy(struct cpufreq_policy *data,
+                                struct cpufreq_policy *policy);
 
 #define CPUFREQ_SHARED_TYPE_NONE (0) /* None */
 #define CPUFREQ_SHARED_TYPE_HW   (1) /* HW does needed coordination */
@@ -64,11 +71,26 @@ struct cpufreq_freqs {
 #define CPUFREQ_GOV_STOP   2
 #define CPUFREQ_GOV_LIMITS 3
 
+struct cpufreq_governor {
+    char    name[CPUFREQ_NAME_LEN];
+    int     (*governor)(struct cpufreq_policy *policy,
+                        unsigned int event);
+};
+
+extern struct cpufreq_governor cpufreq_gov_dbs;
+#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_dbs
+
 /* pass a target to the cpufreq driver */
 extern int __cpufreq_driver_target(struct cpufreq_policy *policy,
                                    unsigned int target_freq,
                                    unsigned int relation);
 extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy);
+
+static __inline__ int 
+__cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
+{
+    return policy->governor->governor(policy, event);
+}
 
 
 /*********************************************************************
@@ -91,7 +113,50 @@ struct cpufreq_driver {
 
 extern struct cpufreq_driver *cpufreq_driver;
 
-void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int 
state);
+static __inline__ 
+int cpufreq_register_driver(struct cpufreq_driver *driver_data)
+{
+    if (!driver_data         || 
+        !driver_data->init   || 
+        !driver_data->exit   || 
+        !driver_data->verify || 
+        !driver_data->target)
+        return -EINVAL;
+
+    if (cpufreq_driver)
+        return -EBUSY;
+
+    cpufreq_driver = driver_data;
+    return 0;
+}
+
+static __inline__ 
+int cpufreq_unregister_driver(struct cpufreq_driver *driver)
+{
+    if (!cpufreq_driver || (driver != cpufreq_driver))
+        return -EINVAL;
+
+    cpufreq_driver = NULL;
+    return 0;
+}
+
+static __inline__
+void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
+                                  unsigned int min, unsigned int max)
+{
+    if (policy->min < min)
+        policy->min = min;
+    if (policy->max < min)
+        policy->max = min;
+    if (policy->min > max)
+        policy->min = max;
+    if (policy->max > max)
+        policy->max = max;
+    if (policy->min > policy->max)
+        policy->min = policy->max;
+    return;
+}
+
 
 /*********************************************************************
  *                     FREQUENCY TABLE HELPERS                       *
@@ -107,6 +172,9 @@ struct cpufreq_frequency_table {
 };
 
 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
+                   struct cpufreq_frequency_table *table);
+
+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
                    struct cpufreq_frequency_table *table);
 
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
diff -r 346c073ed6a4 -r f125e481d8b6 xen/include/acpi/cpufreq/processor_perf.h
--- a/xen/include/acpi/cpufreq/processor_perf.h Thu Sep 11 18:00:06 2008 +0100
+++ b/xen/include/acpi/cpufreq/processor_perf.h Fri Sep 12 10:34:50 2008 +0100
@@ -7,26 +7,23 @@
 #define XEN_PX_INIT 0x80000000
 
 int get_cpu_id(u8);
-int acpi_cpufreq_init(void);
 int powernow_cpufreq_init(void);
 
 void px_statistic_update(cpumask_t, uint8_t, uint8_t);
-int  px_statistic_init(int);
-void px_statistic_reset(int);
-void px_statistic_suspend(void);
-void px_statistic_resume(void);
+int  px_statistic_init(unsigned int);
+void px_statistic_exit(unsigned int);
+void px_statistic_reset(unsigned int);
 
-void cpufreq_dom_exit(void);
-int  cpufreq_dom_init(void);
-int  cpufreq_dom_dbs(unsigned int);
-void cpufreq_suspend(void);
-int  cpufreq_resume(void);
+int  cpufreq_limit_change(unsigned int);
+
+int  cpufreq_add_cpu(unsigned int);
+int  cpufreq_del_cpu(unsigned int);
 
 uint64_t get_cpu_idle_time(unsigned int);
 
 struct processor_performance {
     uint32_t state;
-    uint32_t ppc;
+    uint32_t platform_limit;
     struct xen_pct_register control_register;
     struct xen_pct_register status_register;
     uint32_t state_count;
diff -r 346c073ed6a4 -r f125e481d8b6 xen/include/public/platform.h
--- a/xen/include/public/platform.h     Thu Sep 11 18:00:06 2008 +0100
+++ b/xen/include/public/platform.h     Fri Sep 12 10:34:50 2008 +0100
@@ -289,7 +289,7 @@ struct xen_psd_package {
 
 struct xen_processor_performance {
     uint32_t flags;     /* flag for Px sub info type */
-    uint32_t ppc;       /* Platform limitation on freq usage */
+    uint32_t platform_limit;  /* Platform limitation on freq usage */
     struct xen_pct_register control_register;
     struct xen_pct_register status_register;
     uint32_t state_count;     /* total available performance states */

_______________________________________________
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] x86: Clean up cpufreq core logic, Xen patchbot-unstable <=