cpufreq: xen is default cpufreq, userspace is default governor (override on cmdline)
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 29 Dec 2008 14:08:46 +0000 (14:08 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 29 Dec 2008 14:08:46 +0000 (14:08 +0000)
Set userspace governor as default, which stays same effect
as when cpufreq in xen is not enabled. As a result, enable cpufreq
in xen by default to avoid reboot to activate cpufreq. Now it's
always on but w/o performance impact if user doesn't attempt
to change governor.

Add governor option at cmdline, add some warning info for debug.

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
xen/arch/ia64/xen/cpufreq/cpufreq.c
xen/arch/x86/acpi/cpufreq/cpufreq.c
xen/common/domain.c
xen/drivers/cpufreq/cpufreq.c
xen/drivers/cpufreq/utility.c
xen/include/acpi/cpufreq/cpufreq.h

index c2c311ddea2755c5e9af53c33231cc3dff9fcb97..fdd688810823a75a189893e7590c8fa1c7251a0c 100644 (file)
@@ -226,7 +226,8 @@ acpi_cpufreq_cpu_init (struct cpufreq_policy *policy)
                                data->acpi_data->states[i].transition_latency * 1000;
                }
        }
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+       policy->governor = cpufreq_opt_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);
index 8ddd274a20ca8e491f4b7b40dc4423008f917138..4a6f0abf7b8e6d36cf25ed0678679d7ed75c016b 100644 (file)
@@ -393,8 +393,10 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
 
     drv_write(&cmd);
 
-    if (!check_freqs(cmd.mask, freqs.new, data))
+    if (!check_freqs(cmd.mask, freqs.new, data)) {
+        printk(KERN_WARNING "Fail transfer to new freq %d\n", freqs.new);
         return -EAGAIN;
+    }
 
     for_each_cpu_mask(j, online_policy_cpus)
         cpufreq_statistic_update(j, perf->state, next_perf_state);
@@ -508,7 +510,8 @@ acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
             policy->cpuinfo.transition_latency =
                 perf->states[i].transition_latency * 1000;
     }
-    policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+    policy->governor = cpufreq_opt_governor ? : CPUFREQ_DEFAULT_GOVERNOR;
 
     data->max_freq = perf->states[0].core_frequency * 1000;
     /* table init */
index e94740675e1467631a1570083f1680bddcab33ca..ab807bfbf864efb058e326ef33cf8cbc60bd6d31 100644 (file)
 
 /* Linux config option: propageted to domain0 */
 /* xen_processor_pmbits: xen control Cx, Px, ... */
-unsigned int xen_processor_pmbits = 0;
+unsigned int xen_processor_pmbits = XEN_PROCESSOR_PM_PX;
 
 /* opt_dom0_vcpus_pin: If true, dom0 VCPUs are pinned. */
 static unsigned int opt_dom0_vcpus_pin;
 boolean_param("dom0_vcpus_pin", opt_dom0_vcpus_pin);
 
-enum cpufreq_controller cpufreq_controller;
+/* set xen as default cpufreq */
+enum cpufreq_controller cpufreq_controller = FREQCTL_xen;
+struct cpufreq_governor *cpufreq_opt_governor;
+
 static void __init setup_cpufreq_option(char *str)
 {
     char *arg;
@@ -52,19 +55,35 @@ static void __init setup_cpufreq_option(char *str)
         return;
     }
 
+    if ( !strcmp(str, "none") )
+    {
+        xen_processor_pmbits &= ~XEN_PROCESSOR_PM_PX;
+        cpufreq_controller = FREQCTL_none;
+        return;
+    }
+
     if ( (arg = strpbrk(str, ",:")) != NULL )
         *arg++ = '\0';
 
     if ( !strcmp(str, "xen") )
-    {
-        xen_processor_pmbits |= XEN_PROCESSOR_PM_PX;
-        cpufreq_controller = FREQCTL_xen;
         if ( arg && *arg )
             cpufreq_cmdline_parse(arg);
-    }
 }
 custom_param("cpufreq", setup_cpufreq_option);
 
+static void __init setup_cpufreq_gov_option(char *str)
+{
+    if ( !strcmp(str, "userspace") )
+        cpufreq_opt_governor = &cpufreq_gov_userspace;
+    else if ( !strcmp(str, "performance") )
+        cpufreq_opt_governor = &cpufreq_gov_performance;
+    else if ( !strcmp(str, "powersave") )
+        cpufreq_opt_governor = &cpufreq_gov_powersave;
+    else if ( !strcmp(str, "ondemand") )
+        cpufreq_opt_governor = &cpufreq_gov_dbs;
+}
+custom_param("cpufreq_governor", setup_cpufreq_gov_option);
+
 /* Protect updates/reads (resp.) of domain_list and domain_hash. */
 DEFINE_SPINLOCK(domlist_update_lock);
 DEFINE_RCU_READ_LOCK(domlist_read_lock);
index 169426e373930f0b003425c04e558f4184d646d9..dee38fa513672fa7cbf4049c4a8a7af7e87d1113 100644 (file)
@@ -214,8 +214,20 @@ int cpufreq_add_cpu(unsigned int cpu)
         memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
         policy->governor = NULL;
         ret = __cpufreq_set_policy(policy, &new_policy);
-        if (ret)
-            goto err2;
+        if (ret) {
+            if (new_policy.governor == CPUFREQ_DEFAULT_GOVERNOR)
+                /* if default governor fail, cpufreq really meet troubles */
+                goto err2;
+            else {
+                /* grub option governor fail */
+                /* give one more chance to default gov */
+                memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
+                new_policy.governor = CPUFREQ_DEFAULT_GOVERNOR;
+                ret = __cpufreq_set_policy(policy, &new_policy);
+                if (ret)
+                    goto err2;
+            }
+        }
     }
 
     return 0;
index 1c8176fabe4ed81ff8d95da882ffbe8e80b98847..4ac38339234a755298e7e8721871521f3554e86f 100644 (file)
@@ -360,10 +360,15 @@ int __cpufreq_set_policy(struct cpufreq_policy *data,
         /* start new governor */
         data->governor = policy->governor;
         if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
+            printk(KERN_WARNING "Fail change to %s governor\n",
+                                 data->governor->name);
+
             /* new governor failed, so re-start old one */
             if (old_gov) {
                 data->governor = old_gov;
                 __cpufreq_governor(data, CPUFREQ_GOV_START);
+                printk(KERN_WARNING "Still stay at %s governor\n",
+                                     data->governor->name);
             }
             return -EINVAL;
         }
index 20441ff934de66991adeab7aac1264de22d88c1e..4314414031e0eea5db76c6cb79e2558bea13fa24 100644 (file)
@@ -11,6 +11,9 @@
  * published by the Free Software Foundation.
  */
 
+#ifndef __XEN_CPUFREQ_PM_H__
+#define __XEN_CPUFREQ_PM_H__
+
 #include <xen/types.h>
 #include <xen/list.h>
 #include <xen/cpumask.h>
@@ -85,6 +88,7 @@ struct cpufreq_governor {
     struct list_head governor_list;
 };
 
+extern struct cpufreq_governor *cpufreq_opt_governor;
 extern struct cpufreq_governor cpufreq_gov_dbs;
 extern struct cpufreq_governor cpufreq_gov_userspace;
 extern struct cpufreq_governor cpufreq_gov_performance;
@@ -93,7 +97,7 @@ extern struct cpufreq_governor cpufreq_gov_powersave;
 extern int cpufreq_register_governor(struct cpufreq_governor *governor);
 extern int cpufreq_unregister_governor(struct cpufreq_governor *governor);
 extern struct cpufreq_governor *__find_governor(const char *governor);
-#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_performance
+#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_userspace
 
 /* pass a target to the cpufreq driver */
 extern int __cpufreq_driver_target(struct cpufreq_policy *policy,
@@ -220,3 +224,4 @@ int get_cpufreq_ondemand_para(uint32_t *sampling_rate_max,
                               uint32_t *up_threshold);
 int write_ondemand_sampling_rate(unsigned int sampling_rate);
 int write_ondemand_up_threshold(unsigned int up_threshold);
+#endif /* __XEN_CPUFREQ_PM_H__ */