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: Add cpufreq logic to S3 suspend/resu

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86: Add cpufreq logic to S3 suspend/resume
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Sat, 28 Jun 2008 16:00:39 -0700
Delivery-date: Sat, 28 Jun 2008 16:02:07 -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 1214579807 -3600
# Node ID baaea9f0db5eb153de5bb89e09f084a98e28ae99
# Parent  2ac9155a85c110dd25c963c8fa625c476556b474
x86: Add cpufreq logic to S3 suspend/resume

When suspend to S3, stop the cpufreq dbs governor. When resume from
S3, firstly sync cpu state and freq at the 1st dbs timer; from 2nd dbs
timer on, cpufreq dbs governor control cpu px transfer according to
its workload algorithm. Px statistic is also handled.

Signed-off-by: Liu Jinsong <jinsong.liu@xxxxxxxxx>
---
 xen/arch/x86/acpi/cpufreq/cpufreq.c          |  139 +++++++++++++++++----------
 xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c |   12 +-
 xen/arch/x86/acpi/cpufreq/utility.c          |   86 ++++++++++++++++
 xen/arch/x86/acpi/power.c                    |    5 
 xen/include/acpi/cpufreq/cpufreq.h           |    3 
 xen/include/acpi/cpufreq/processor_perf.h    |    7 +
 6 files changed, 201 insertions(+), 51 deletions(-)

diff -r 2ac9155a85c1 -r baaea9f0db5e xen/arch/x86/acpi/cpufreq/cpufreq.c
--- a/xen/arch/x86/acpi/cpufreq/cpufreq.c       Fri Jun 27 16:12:14 2008 +0100
+++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c       Fri Jun 27 16:16:47 2008 +0100
@@ -47,6 +47,10 @@ struct processor_pminfo processor_pminfo
 struct processor_pminfo processor_pminfo[NR_CPUS];
 struct cpufreq_policy xen_px_policy[NR_CPUS];
 
+static cpumask_t *cpufreq_dom_pt;
+static cpumask_t cpufreq_dom_mask;
+static unsigned int cpufreq_dom_max;
+
 enum {
     UNDEFINED_CAPABLE = 0,
     SYSTEM_INTEL_MSR_CAPABLE,
@@ -60,7 +64,6 @@ struct acpi_cpufreq_data {
     struct processor_performance *acpi_data;
     struct cpufreq_frequency_table *freq_table;
     unsigned int max_freq;
-    unsigned int resume;
     unsigned int cpu_feature;
 };
 
@@ -328,14 +331,16 @@ static int acpi_cpufreq_target(struct cp
 
     next_perf_state = data->freq_table[next_state].index;
     if (perf->state == next_perf_state) {
-        if (unlikely(data->resume)) {
-            printk("xen_pminfo: @acpi_cpufreq_target, "
-                "Called after resume, resetting to P%d\n", 
+        if (unlikely(policy->resume)) {
+            printk(KERN_INFO "Called after resume, resetting to P%d\n", 
                 next_perf_state);
-            data->resume = 0;
+            policy->resume = 0;
         }
-        else
+        else {
+            printk(KERN_INFO "Already at target state (P%d)\n", 
+                next_perf_state);
             return 0;
+        }
     }
 
     switch (data->cpu_feature) {
@@ -531,7 +536,7 @@ acpi_cpufreq_cpu_init(struct cpufreq_pol
      * the first call to ->target() should result in us actually
      * writing something to the appropriate registers.
      */
-    data->resume = 1;
+    policy->resume = 1;
 
     return result;
 
@@ -549,61 +554,101 @@ static struct cpufreq_driver acpi_cpufre
     .init   = acpi_cpufreq_cpu_init,
 };
 
-int acpi_cpufreq_init(void)
-{
-    unsigned int i, ret = 0;
-    unsigned int dom, max_dom = 0;
-    cpumask_t *pt, dom_mask;
-
-    cpus_clear(dom_mask);
+void cpufreq_dom_exit(void)
+{
+    cpufreq_dom_max = 0;
+    cpus_clear(cpufreq_dom_mask);
+    if (cpufreq_dom_pt)
+        xfree(cpufreq_dom_pt);
+}
+
+int cpufreq_dom_init(void)
+{
+    unsigned int i;
+
+    cpufreq_dom_max = 0;
+    cpus_clear(cpufreq_dom_mask);
 
     for_each_online_cpu(i) {
-        cpu_set(processor_pminfo[i].perf.domain_info.domain, dom_mask);
-        if (max_dom < processor_pminfo[i].perf.domain_info.domain)
-            max_dom = processor_pminfo[i].perf.domain_info.domain;
-    }
-    max_dom++;
-
-    pt = xmalloc_array(cpumask_t, max_dom);
-    if (!pt)
+        cpu_set(processor_pminfo[i].perf.domain_info.domain, cpufreq_dom_mask);
+        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_pt = xmalloc_array(cpumask_t, cpufreq_dom_max);
+    if (!cpufreq_dom_pt)
         return -ENOMEM;
-    memset(pt, 0, max_dom * sizeof(cpumask_t));
-
-    /* get cpumask of each psd domain */
+    memset(cpufreq_dom_pt, 0, cpufreq_dom_max * sizeof(cpumask_t));
+
     for_each_online_cpu(i)
-        cpu_set(i, pt[processor_pminfo[i].perf.domain_info.domain]);
+        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 = 
-            pt[processor_pminfo[i].perf.domain_info.domain];
-
-    cpufreq_driver = &acpi_cpufreq_driver;
-
-    /* setup cpufreq infrastructure */
+        processor_pminfo[i].perf.shared_cpu_map =
+            cpufreq_dom_pt[processor_pminfo[i].perf.domain_info.domain];
+
+    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)
-            goto out;
+            return ret;
 
         ret = acpi_cpufreq_cpu_init(&xen_px_policy[i]);
         if (ret)
-            goto out;
-    }
-
-    /* setup ondemand cpufreq */
-    for (dom=0; dom<max_dom; dom++) {
-        if (!cpu_isset(dom, dom_mask))
+            return ret;
+    }
+    return ret;
+}
+
+int cpufreq_dom_dbs(unsigned int event)
+{
+    int cpu, dom, ret = 0;
+
+    for (dom=0; dom<cpufreq_dom_max; dom++) {
+        if (!cpu_isset(dom, cpufreq_dom_mask))
             continue;
-        i = first_cpu(pt[dom]);
-        ret = cpufreq_governor_dbs(&xen_px_policy[i], CPUFREQ_GOV_START);
+        cpu = first_cpu(cpufreq_dom_pt[dom]);
+        ret = cpufreq_governor_dbs(&xen_px_policy[cpu], event);
         if (ret)
-            goto out;
-    }
-
-out:
-    xfree(pt);
-   
+            return ret;
+    }
     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;
+}
diff -r 2ac9155a85c1 -r baaea9f0db5e 
xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c
--- a/xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c      Fri Jun 27 16:12:14 
2008 +0100
+++ b/xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c      Fri Jun 27 16:16:47 
2008 +0100
@@ -79,6 +79,12 @@ static void dbs_check_cpu(struct cpu_dbs
         return;
 
     policy = this_dbs_info->cur_policy;
+
+    if (unlikely(policy->resume)) {
+        __cpufreq_driver_target(policy, policy->max,CPUFREQ_RELATION_H);
+        return;
+    }
+
     cur_ns = NOW();
     total_ns = cur_ns - this_dbs_info->prev_cpu_wall;
     this_dbs_info->prev_cpu_wall = NOW();
@@ -217,8 +223,7 @@ int cpufreq_governor_dbs(struct cpufreq_
         break;
 
     case CPUFREQ_GOV_STOP:
-        if (this_dbs_info->enable)
-            dbs_timer_exit(this_dbs_info);
+        dbs_timer_exit(this_dbs_info);
         dbs_enable--;
 
         break;
@@ -233,5 +238,4 @@ int cpufreq_governor_dbs(struct cpufreq_
         break;
     }
     return 0;
-}
-             
+} 
diff -r 2ac9155a85c1 -r baaea9f0db5e xen/arch/x86/acpi/cpufreq/utility.c
--- a/xen/arch/x86/acpi/cpufreq/utility.c       Fri Jun 27 16:12:14 2008 +0100
+++ b/xen/arch/x86/acpi/cpufreq/utility.c       Fri Jun 27 16:16:47 2008 +0100
@@ -36,6 +36,33 @@ struct cpufreq_driver *cpufreq_driver;
 /*********************************************************************
  *                    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];
+        pxpt->u.pt[pxpt->u.cur].residency +=
+                    now - pxpt->prev_state_wall;
+    }
+}
+
+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;
+    }
+}
 
 void px_statistic_update(cpumask_t cpumask, uint8_t from, uint8_t to)
 {
@@ -242,3 +269,62 @@ int __cpufreq_driver_getavg(struct cpufr
 
     return ret;
 }
+
+
+/*********************************************************************
+ *               CPUFREQ SUSPEND/RESUME                              *
+ *********************************************************************/
+
+void cpufreq_suspend(void)
+{
+    int cpu;
+
+    /* to protect the case when Px was controlled by dom0-kernel */
+    /* or when CPU_FREQ not set in which case ACPI Px objects not parsed */
+    for_each_online_cpu(cpu) {
+        struct processor_performance *perf = &processor_pminfo[cpu].perf;
+
+        if (!perf->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 controlled by dom0-kernel */
+    /* or when CPU_FREQ not set in which case ACPI Px objects not parsed */
+    /* 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)
+            goto err;
+        perf->state = 0;
+        policy->resume = 1;
+    }
+
+    px_statistic_resume();
+
+    ret = cpufreq_dom_init();
+    if (ret)
+        goto err;
+
+    ret = cpufreq_dom_dbs(CPUFREQ_GOV_START);
+    if (ret)
+        goto err;
+
+    return ret;
+
+err:
+    cpufreq_dom_exit();
+    return ret;
+}
diff -r 2ac9155a85c1 -r baaea9f0db5e xen/arch/x86/acpi/power.c
--- a/xen/arch/x86/acpi/power.c Fri Jun 27 16:12:14 2008 +0100
+++ b/xen/arch/x86/acpi/power.c Fri Jun 27 16:16:47 2008 +0100
@@ -27,6 +27,8 @@
 #include <public/platform.h>
 #include <asm/tboot.h>
 
+#include <acpi/cpufreq/cpufreq.h>
+
 static char opt_acpi_sleep[20];
 string_param("acpi_sleep", opt_acpi_sleep);
 
@@ -125,6 +127,8 @@ static int enter_state(u32 state)
     printk(XENLOG_INFO "Preparing system for ACPI S%d state.", state);
 
     freeze_domains();
+
+    cpufreq_suspend();
 
     disable_nonboot_cpus();
     if ( num_online_cpus() != 1 )
@@ -181,6 +185,7 @@ static int enter_state(u32 state)
 
  enable_cpu:
     enable_nonboot_cpus();
+    cpufreq_resume();
     thaw_domains();
     spin_unlock(&pm_lock);
     return error;
diff -r 2ac9155a85c1 -r baaea9f0db5e xen/include/acpi/cpufreq/cpufreq.h
--- a/xen/include/acpi/cpufreq/cpufreq.h        Fri Jun 27 16:12:14 2008 +0100
+++ b/xen/include/acpi/cpufreq/cpufreq.h        Fri Jun 27 16:16:47 2008 +0100
@@ -36,7 +36,10 @@ struct cpufreq_policy {
     unsigned int        max;    /* in kHz */
     unsigned int        cur;    /* in kHz, only needed if cpufreq
                                  * governors are used */
+    unsigned int        resume; /* flag for cpufreq 1st run
+                                 * S3 wakeup, hotplug cpu, etc */
 };
+extern struct cpufreq_policy xen_px_policy[NR_CPUS];
 
 #define CPUFREQ_SHARED_TYPE_NONE (0) /* None */
 #define CPUFREQ_SHARED_TYPE_HW   (1) /* HW does needed coordination */
diff -r 2ac9155a85c1 -r baaea9f0db5e xen/include/acpi/cpufreq/processor_perf.h
--- a/xen/include/acpi/cpufreq/processor_perf.h Fri Jun 27 16:12:14 2008 +0100
+++ b/xen/include/acpi/cpufreq/processor_perf.h Fri Jun 27 16:16:47 2008 +0100
@@ -10,6 +10,13 @@ void px_statistic_update(cpumask_t, uint
 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);
+void cpufreq_dom_exit(void);
+int  cpufreq_dom_init(void);
+int  cpufreq_dom_dbs(unsigned int);
+void cpufreq_suspend(void);
+int  cpufreq_resume(void);
 
 struct processor_performance {
     uint32_t state;

_______________________________________________
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: Add cpufreq logic to S3 suspend/resume, Xen patchbot-unstable <=