X86 and IA64: Rebase cpufreq logic for supporting both x86 and ia64

arch

Rebase cpufreq logic for supporting both x86 and ia64 arch:
1. move cpufreq arch-independent logic into common dir
(xen/drivers/acpi
and xen/drivers/cpufreq dir);
2. leave cpufreq x86-dependent logic at xen/arch/x86/acpi/cpufreq dir;

Signed-off-by: Yu, Ke <ke.yu@intel.com>
Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
This commit is contained in:
Keir Fraser committed 2008-09-26 14:04:38 +01:00
1 parent 77fd4d4b32
commit 6b4ce8b388
12 files changed
+219 -171

No files matched your search

-1
View File
@@ -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
-2
View File
@@ -1,4 +1,2 @@
obj-y += cpufreq.o
obj-y += utility.o
obj-y += cpufreq_ondemand.o
obj-y += powernow.o
+2 -151
View File
@@ -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;
+1
View File
@@ -1,4 +1,5 @@
subdir-y += char
subdir-y += cpufreq
subdir-$(x86) += passthrough
subdir-$(HAS_ACPI) += acpi
subdir-$(HAS_VGA) += video
+1
View File
@@ -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
@@ -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;
}
+3
View File
@@ -0,0 +1,3 @@
obj-y += cpufreq.o
obj-y += cpufreq_ondemand.o
obj-y += utility.o
+188
View File
@@ -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;
}
@@ -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 )
+7
View File
@@ -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;
+5 -5
View File
@@ -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__ */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.