aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/acpi/Makefile1
-rw-r--r--xen/arch/x86/acpi/cpufreq/Makefile2
-rw-r--r--xen/arch/x86/acpi/cpufreq/cpufreq.c153
-rw-r--r--xen/drivers/Makefile1
-rw-r--r--xen/drivers/acpi/Makefile1
-rw-r--r--xen/drivers/acpi/pmstat.c (renamed from xen/arch/x86/acpi/pmstat.c)6
-rw-r--r--xen/drivers/cpufreq/Makefile3
-rw-r--r--xen/drivers/cpufreq/cpufreq.c188
-rw-r--r--xen/drivers/cpufreq/cpufreq_ondemand.c (renamed from xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c)0
-rw-r--r--xen/drivers/cpufreq/utility.c (renamed from xen/arch/x86/acpi/cpufreq/utility.c)18
-rw-r--r--xen/include/acpi/cpufreq/cpufreq.h7
-rw-r--r--xen/include/acpi/cpufreq/processor_perf.h10
12 files changed, 219 insertions, 171 deletions
diff --git a/xen/arch/x86/acpi/Makefile b/xen/arch/x86/acpi/Makefile
index d98d77d654..f31302c368 100644
--- a/xen/arch/x86/acpi/Makefile
+++ b/xen/arch/x86/acpi/Makefile
@@ -2,4 +2,3 @@ subdir-y += cpufreq
obj-y += boot.o
obj-y += power.o suspend.o wakeup_prot.o cpu_idle.o cpuidle_menu.o
-obj-y += pmstat.o
diff --git a/xen/arch/x86/acpi/cpufreq/Makefile b/xen/arch/x86/acpi/cpufreq/Makefile
index 5debfe7ccf..f75da9b9ca 100644
--- a/xen/arch/x86/acpi/cpufreq/Makefile
+++ b/xen/arch/x86/acpi/cpufreq/Makefile
@@ -1,4 +1,2 @@
obj-y += cpufreq.o
-obj-y += utility.o
-obj-y += cpufreq_ondemand.o
obj-y += powernow.o
diff --git a/xen/arch/x86/acpi/cpufreq/cpufreq.c b/xen/arch/x86/acpi/cpufreq/cpufreq.c
index 119d8ff86d..b706d113c9 100644
--- a/xen/arch/x86/acpi/cpufreq/cpufreq.c
+++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c
@@ -45,9 +45,6 @@
#include <acpi/acpi.h>
#include <acpi/cpufreq/cpufreq.h>
-/* TODO: change to link list later as domain number may be sparse */
-static cpumask_t cpufreq_dom_map[NR_CPUS];
-
enum {
UNDEFINED_CAPABLE = 0,
SYSTEM_INTEL_MSR_CAPABLE,
@@ -57,13 +54,6 @@ enum {
#define INTEL_MSR_RANGE (0xffff)
#define CPUID_6_ECX_APERFMPERF_CAPABILITY (0x1)
-struct acpi_cpufreq_data {
- struct processor_performance *acpi_data;
- struct cpufreq_frequency_table *freq_table;
- unsigned int max_freq;
- unsigned int cpu_feature;
-};
-
static struct acpi_cpufreq_data *drv_data[NR_CPUS];
static struct cpufreq_driver acpi_cpufreq_driver;
@@ -342,7 +332,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
policy->resume = 0;
}
else {
- printk(KERN_INFO "Already at target state (P%d)\n",
+ printk(KERN_DEBUG "Already at target state (P%d)\n",
next_perf_state);
return 0;
}
@@ -379,7 +369,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
if (!check_freqs(cmd.mask, freqs.new, data))
return -EAGAIN;
- px_statistic_update(cmd.mask, perf->state, next_perf_state);
+ cpufreq_statistic_update(cmd.mask, perf->state, next_perf_state);
perf->state = next_perf_state;
policy->cur = freqs.new;
@@ -581,145 +571,6 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
.exit = acpi_cpufreq_cpu_exit,
};
-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 || !processor_pminfo[cpu])
- 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 (!processor_pminfo[cpu] || !(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;
-
-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_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 (!processor_pminfo[cpu] || !(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;
diff --git a/xen/drivers/Makefile b/xen/drivers/Makefile
index 805fe1f77b..e88cd2ffe8 100644
--- a/xen/drivers/Makefile
+++ b/xen/drivers/Makefile
@@ -1,4 +1,5 @@
subdir-y += char
+subdir-y += cpufreq
subdir-$(x86) += passthrough
subdir-$(HAS_ACPI) += acpi
subdir-$(HAS_VGA) += video
diff --git a/xen/drivers/acpi/Makefile b/xen/drivers/acpi/Makefile
index cc6acbe5dd..7d108c43a9 100644
--- a/xen/drivers/acpi/Makefile
+++ b/xen/drivers/acpi/Makefile
@@ -4,6 +4,7 @@ subdir-y += utilities
obj-y += tables.o
obj-y += numa.o
obj-y += osl.o
+obj-y += pmstat.o
obj-$(x86) += hwregs.o
obj-$(x86) += reboot.o
diff --git a/xen/arch/x86/acpi/pmstat.c b/xen/drivers/acpi/pmstat.c
index e15b244b1b..1a0a052100 100644
--- a/xen/arch/x86/acpi/pmstat.c
+++ b/xen/drivers/acpi/pmstat.c
@@ -41,7 +41,7 @@
#include <public/sysctl.h>
#include <acpi/cpufreq/cpufreq.h>
-struct pm_px *__read_mostly px_statistic_data[NR_CPUS];
+struct pm_px *__read_mostly cpufreq_statistic_data[NR_CPUS];
extern uint32_t pmstat_get_cx_nr(uint32_t cpuid);
extern int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat);
@@ -84,7 +84,7 @@ int do_get_pm_info(struct xen_sysctl_get_pmstat *op)
uint64_t now, ct;
uint64_t total_idle_ns;
uint64_t tmp_idle_ns;
- struct pm_px *pxpt = px_statistic_data[op->cpuid];
+ struct pm_px *pxpt = cpufreq_statistic_data[op->cpuid];
if ( !pxpt )
return -ENODATA;
@@ -122,7 +122,7 @@ int do_get_pm_info(struct xen_sysctl_get_pmstat *op)
case PMSTAT_reset_pxstat:
{
- px_statistic_reset(op->cpuid);
+ cpufreq_statistic_reset(op->cpuid);
break;
}
diff --git a/xen/drivers/cpufreq/Makefile b/xen/drivers/cpufreq/Makefile
new file mode 100644
index 0000000000..c91c25b715
--- /dev/null
+++ b/xen/drivers/cpufreq/Makefile
@@ -0,0 +1,3 @@
+obj-y += cpufreq.o
+obj-y += cpufreq_ondemand.o
+obj-y += utility.o
diff --git a/xen/drivers/cpufreq/cpufreq.c b/xen/drivers/cpufreq/cpufreq.c
new file mode 100644
index 0000000000..d4dae5bfd3
--- /dev/null
+++ b/xen/drivers/cpufreq/cpufreq.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
+ * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
+ * Copyright (C) 2002 - 2004 Dominik Brodowski <linux@brodo.de>
+ * Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com>
+ *
+ * Feb 2008 - Liu Jinsong <jinsong.liu@intel.com>
+ * Add cpufreq limit change handle and per-cpu cpufreq add/del
+ * to cope with cpu hotplug
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#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/msr.h>
+#include <asm/io.h>
+#include <asm/config.h>
+#include <asm/processor.h>
+#include <asm/percpu.h>
+#include <asm/cpufeature.h>
+#include <acpi/acpi.h>
+#include <acpi/cpufreq/cpufreq.h>
+
+/* TODO: change to link list later as domain number may be sparse */
+static cpumask_t cpufreq_dom_map[NR_CPUS];
+
+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 || !processor_pminfo[cpu])
+ 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 (!processor_pminfo[cpu] || !(perf->init & XEN_PX_INIT))
+ return 0;
+
+ if (cpu_is_offline(cpu) || cpufreq_cpu_policy[cpu])
+ return -EINVAL;
+
+ ret = cpufreq_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) {
+ cpufreq_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;
+
+err2:
+ cpufreq_driver->exit(policy);
+err1:
+ for_each_cpu_mask(j, cpufreq_dom_map[dom]) {
+ cpufreq_cpu_policy[j] = NULL;
+ cpufreq_statistic_exit(j);
+ }
+
+ cpus_clear(cpufreq_dom_map[dom]);
+ xfree(policy);
+ return ret;
+}
+
+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 (!processor_pminfo[cpu] || !(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]);
+ cpufreq_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;
+}
+
diff --git a/xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c b/xen/drivers/cpufreq/cpufreq_ondemand.c
index f1b676c2f4..f1b676c2f4 100644
--- a/xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c
+++ b/xen/drivers/cpufreq/cpufreq_ondemand.c
diff --git a/xen/arch/x86/acpi/cpufreq/utility.c b/xen/drivers/cpufreq/utility.c
index 96606f17c0..eaf8ab8d33 100644
--- a/xen/arch/x86/acpi/cpufreq/utility.c
+++ b/xen/drivers/cpufreq/utility.c
@@ -39,7 +39,7 @@ struct cpufreq_policy *__read_mostly cpufreq_cpu_policy[NR_CPUS];
* Px STATISTIC INFO *
*********************************************************************/
-void px_statistic_update(cpumask_t cpumask, uint8_t from, uint8_t to)
+void cpufreq_statistic_update(cpumask_t cpumask, uint8_t from, uint8_t to)
{
uint32_t i;
uint64_t now;
@@ -47,7 +47,7 @@ void px_statistic_update(cpumask_t cpumask, uint8_t from, uint8_t to)
now = NOW();
for_each_cpu_mask(i, cpumask) {
- struct pm_px *pxpt = px_statistic_data[i];
+ struct pm_px *pxpt = cpufreq_statistic_data[i];
struct processor_pminfo *pmpt = processor_pminfo[i];
uint64_t total_idle_ns;
uint64_t tmp_idle_ns;
@@ -71,10 +71,10 @@ void px_statistic_update(cpumask_t cpumask, uint8_t from, uint8_t to)
}
}
-int px_statistic_init(unsigned int cpuid)
+int cpufreq_statistic_init(unsigned int cpuid)
{
uint32_t i, count;
- struct pm_px *pxpt = px_statistic_data[cpuid];
+ struct pm_px *pxpt = cpufreq_statistic_data[cpuid];
const struct processor_pminfo *pmpt = processor_pminfo[cpuid];
count = pmpt->perf.state_count;
@@ -88,7 +88,7 @@ int px_statistic_init(unsigned int cpuid)
if ( !pxpt )
return -ENOMEM;
memset(pxpt, 0, sizeof(*pxpt));
- px_statistic_data[cpuid] = pxpt;
+ cpufreq_statistic_data[cpuid] = pxpt;
}
pxpt->u.trans_pt = xmalloc_array(uint64_t, count * count);
@@ -116,9 +116,9 @@ int px_statistic_init(unsigned int cpuid)
return 0;
}
-void px_statistic_exit(unsigned int cpuid)
+void cpufreq_statistic_exit(unsigned int cpuid)
{
- struct pm_px *pxpt = px_statistic_data[cpuid];
+ struct pm_px *pxpt = cpufreq_statistic_data[cpuid];
if (!pxpt)
return;
@@ -127,10 +127,10 @@ void px_statistic_exit(unsigned int cpuid)
memset(pxpt, 0, sizeof(struct pm_px));
}
-void px_statistic_reset(unsigned int cpuid)
+void cpufreq_statistic_reset(unsigned int cpuid)
{
uint32_t i, j, count;
- struct pm_px *pxpt = px_statistic_data[cpuid];
+ struct pm_px *pxpt = cpufreq_statistic_data[cpuid];
const struct processor_pminfo *pmpt = processor_pminfo[cpuid];
if ( !pxpt || !pmpt )
diff --git a/xen/include/acpi/cpufreq/cpufreq.h b/xen/include/acpi/cpufreq/cpufreq.h
index 59ceac34f5..77824417ed 100644
--- a/xen/include/acpi/cpufreq/cpufreq.h
+++ b/xen/include/acpi/cpufreq/cpufreq.h
@@ -21,6 +21,13 @@
struct cpufreq_governor;
+struct acpi_cpufreq_data {
+ struct processor_performance *acpi_data;
+ struct cpufreq_frequency_table *freq_table;
+ unsigned int max_freq;
+ unsigned int cpu_feature;
+};
+
struct cpufreq_cpuinfo {
unsigned int max_freq;
unsigned int min_freq;
diff --git a/xen/include/acpi/cpufreq/processor_perf.h b/xen/include/acpi/cpufreq/processor_perf.h
index 75afcf3f23..1bec3c43e3 100644
--- a/xen/include/acpi/cpufreq/processor_perf.h
+++ b/xen/include/acpi/cpufreq/processor_perf.h
@@ -9,10 +9,10 @@
int get_cpu_id(u8);
int powernow_cpufreq_init(void);
-void px_statistic_update(cpumask_t, uint8_t, uint8_t);
-int px_statistic_init(unsigned int);
-void px_statistic_exit(unsigned int);
-void px_statistic_reset(unsigned int);
+void cpufreq_statistic_update(cpumask_t, uint8_t, uint8_t);
+int cpufreq_statistic_init(unsigned int);
+void cpufreq_statistic_exit(unsigned int);
+void cpufreq_statistic_reset(unsigned int);
int cpufreq_limit_change(unsigned int);
@@ -58,6 +58,6 @@ struct pm_px {
uint64_t prev_idle_wall;
};
-extern struct pm_px *px_statistic_data[NR_CPUS];
+extern struct pm_px *cpufreq_statistic_data[NR_CPUS];
#endif /* __XEN_PROCESSOR_PM_H__ */