提交 4c5cdb1e 编写于 作者: L Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq

* master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq:
  [CPUFREQ] Fix up whitespace in conservative governor.
  [CPUFREQ] Make cpufreq_conservative handle out-of-sync events properly
  [CPUFREQ] architectural pstate driver for powernow-k8
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#define PFX "powernow-k8: " #define PFX "powernow-k8: "
#define BFX PFX "BIOS error: " #define BFX PFX "BIOS error: "
#define VERSION "version 2.00.00" #define VERSION "version 2.20.00"
#include "powernow-k8.h" #include "powernow-k8.h"
/* serialize freq changes */ /* serialize freq changes */
...@@ -73,33 +73,11 @@ static u32 find_khz_freq_from_fid(u32 fid) ...@@ -73,33 +73,11 @@ static u32 find_khz_freq_from_fid(u32 fid)
return 1000 * find_freq_from_fid(fid); return 1000 * find_freq_from_fid(fid);
} }
/* Return a frequency in MHz, given an input fid and did */ static u32 find_khz_freq_from_pstate(struct cpufreq_frequency_table *data, u32 pstate)
static u32 find_freq_from_fiddid(u32 fid, u32 did)
{ {
if (current_cpu_data.x86 == 0x10) return data[pstate].frequency;
return 100 * (fid + 0x10) >> did;
else
return 100 * (fid + 0x8) >> did;
} }
static u32 find_khz_freq_from_fiddid(u32 fid, u32 did)
{
return 1000 * find_freq_from_fiddid(fid, did);
}
static u32 find_fid_from_pstate(u32 pstate)
{
u32 hi, lo;
rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi);
return lo & HW_PSTATE_FID_MASK;
}
static u32 find_did_from_pstate(u32 pstate)
{
u32 hi, lo;
rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi);
return (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT;
}
/* Return the vco fid for an input fid /* Return the vco fid for an input fid
* *
...@@ -142,9 +120,7 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data) ...@@ -142,9 +120,7 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data)
if (cpu_family == CPU_HW_PSTATE) { if (cpu_family == CPU_HW_PSTATE) {
rdmsr(MSR_PSTATE_STATUS, lo, hi); rdmsr(MSR_PSTATE_STATUS, lo, hi);
i = lo & HW_PSTATE_MASK; i = lo & HW_PSTATE_MASK;
rdmsr(MSR_PSTATE_DEF_BASE + i, lo, hi); data->currpstate = i;
data->currfid = lo & HW_PSTATE_FID_MASK;
data->currdid = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT;
return 0; return 0;
} }
do { do {
...@@ -295,7 +271,7 @@ static int decrease_vid_code_by_step(struct powernow_k8_data *data, u32 reqvid, ...@@ -295,7 +271,7 @@ static int decrease_vid_code_by_step(struct powernow_k8_data *data, u32 reqvid,
static int transition_pstate(struct powernow_k8_data *data, u32 pstate) static int transition_pstate(struct powernow_k8_data *data, u32 pstate)
{ {
wrmsr(MSR_PSTATE_CTRL, pstate, 0); wrmsr(MSR_PSTATE_CTRL, pstate, 0);
data->currfid = find_fid_from_pstate(pstate); data->currpstate = pstate;
return 0; return 0;
} }
...@@ -845,17 +821,20 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) ...@@ -845,17 +821,20 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table) static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table)
{ {
int i; int i;
u32 hi = 0, lo = 0;
rdmsr(MSR_PSTATE_CUR_LIMIT, hi, lo);
data->max_hw_pstate = (hi & HW_PSTATE_MAX_MASK) >> HW_PSTATE_MAX_SHIFT;
for (i = 0; i < data->acpi_data.state_count; i++) { for (i = 0; i < data->acpi_data.state_count; i++) {
u32 index; u32 index;
u32 hi = 0, lo = 0; u32 hi = 0, lo = 0;
u32 fid;
u32 did;
index = data->acpi_data.states[i].control & HW_PSTATE_MASK; index = data->acpi_data.states[i].control & HW_PSTATE_MASK;
if (index > MAX_HW_PSTATE) { if (index > data->max_hw_pstate) {
printk(KERN_ERR PFX "invalid pstate %d - bad value %d.\n", i, index); printk(KERN_ERR PFX "invalid pstate %d - bad value %d.\n", i, index);
printk(KERN_ERR PFX "Please report to BIOS manufacturer\n"); printk(KERN_ERR PFX "Please report to BIOS manufacturer\n");
powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
continue;
} }
rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi); rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
if (!(hi & HW_PSTATE_VALID_MASK)) { if (!(hi & HW_PSTATE_VALID_MASK)) {
...@@ -864,22 +843,9 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpuf ...@@ -864,22 +843,9 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpuf
continue; continue;
} }
fid = lo & HW_PSTATE_FID_MASK; powernow_table[i].index = index;
did = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT;
dprintk(" %d : fid 0x%x, did 0x%x\n", index, fid, did); powernow_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000;
powernow_table[i].index = index | (fid << HW_FID_INDEX_SHIFT) | (did << HW_DID_INDEX_SHIFT);
powernow_table[i].frequency = find_khz_freq_from_fiddid(fid, did);
if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) {
printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n",
powernow_table[i].frequency,
(unsigned int) (data->acpi_data.states[i].core_frequency * 1000));
powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
continue;
}
} }
return 0; return 0;
} }
...@@ -1020,22 +986,18 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned i ...@@ -1020,22 +986,18 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned i
/* Take a frequency, and issue the hardware pstate transition command */ /* Take a frequency, and issue the hardware pstate transition command */
static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned int index) static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned int index)
{ {
u32 fid = 0;
u32 did = 0;
u32 pstate = 0; u32 pstate = 0;
int res, i; int res, i;
struct cpufreq_freqs freqs; struct cpufreq_freqs freqs;
dprintk("cpu %d transition to index %u\n", smp_processor_id(), index); dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
/* get fid did for hardware pstate transition */ /* get MSR index for hardware pstate transition */
pstate = index & HW_PSTATE_MASK; pstate = index & HW_PSTATE_MASK;
if (pstate > MAX_HW_PSTATE) if (pstate > data->max_hw_pstate)
return 0; return 0;
fid = (index & HW_FID_INDEX_MASK) >> HW_FID_INDEX_SHIFT; freqs.old = find_khz_freq_from_pstate(data->powernow_table, data->currpstate);
did = (index & HW_DID_INDEX_MASK) >> HW_DID_INDEX_SHIFT; freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate);
freqs.old = find_khz_freq_from_fiddid(data->currfid, data->currdid);
freqs.new = find_khz_freq_from_fiddid(fid, did);
for_each_cpu_mask(i, *(data->available_cores)) { for_each_cpu_mask(i, *(data->available_cores)) {
freqs.cpu = i; freqs.cpu = i;
...@@ -1043,9 +1005,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i ...@@ -1043,9 +1005,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i
} }
res = transition_pstate(data, pstate); res = transition_pstate(data, pstate);
data->currfid = find_fid_from_pstate(pstate); freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate);
data->currdid = find_did_from_pstate(pstate);
freqs.new = find_khz_freq_from_fiddid(data->currfid, data->currdid);
for_each_cpu_mask(i, *(data->available_cores)) { for_each_cpu_mask(i, *(data->available_cores)) {
freqs.cpu = i; freqs.cpu = i;
...@@ -1090,10 +1050,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi ...@@ -1090,10 +1050,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
if (query_current_values_with_pending_wait(data)) if (query_current_values_with_pending_wait(data))
goto err_out; goto err_out;
if (cpu_family == CPU_HW_PSTATE) if (cpu_family != CPU_HW_PSTATE) {
dprintk("targ: curr fid 0x%x, did 0x%x\n",
data->currfid, data->currdid);
else {
dprintk("targ: curr fid 0x%x, vid 0x%x\n", dprintk("targ: curr fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid); data->currfid, data->currvid);
...@@ -1124,7 +1081,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi ...@@ -1124,7 +1081,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
mutex_unlock(&fidvid_mutex); mutex_unlock(&fidvid_mutex);
if (cpu_family == CPU_HW_PSTATE) if (cpu_family == CPU_HW_PSTATE)
pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid); pol->cur = find_khz_freq_from_pstate(data->powernow_table, newstate);
else else
pol->cur = find_khz_freq_from_fid(data->currfid); pol->cur = find_khz_freq_from_fid(data->currfid);
ret = 0; ret = 0;
...@@ -1223,7 +1180,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) ...@@ -1223,7 +1180,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
+ (3 * (1 << data->irt) * 10)) * 1000; + (3 * (1 << data->irt) * 10)) * 1000;
if (cpu_family == CPU_HW_PSTATE) if (cpu_family == CPU_HW_PSTATE)
pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid); pol->cur = find_khz_freq_from_pstate(data->powernow_table, data->currpstate);
else else
pol->cur = find_khz_freq_from_fid(data->currfid); pol->cur = find_khz_freq_from_fid(data->currfid);
dprintk("policy current frequency %d kHz\n", pol->cur); dprintk("policy current frequency %d kHz\n", pol->cur);
...@@ -1240,8 +1197,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) ...@@ -1240,8 +1197,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu); cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
if (cpu_family == CPU_HW_PSTATE) if (cpu_family == CPU_HW_PSTATE)
dprintk("cpu_init done, current fid 0x%x, did 0x%x\n", dprintk("cpu_init done, current pstate 0x%x\n", data->currpstate);
data->currfid, data->currdid);
else else
dprintk("cpu_init done, current fid 0x%x, vid 0x%x\n", dprintk("cpu_init done, current fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid); data->currfid, data->currvid);
...@@ -1297,7 +1253,7 @@ static unsigned int powernowk8_get (unsigned int cpu) ...@@ -1297,7 +1253,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
goto out; goto out;
if (cpu_family == CPU_HW_PSTATE) if (cpu_family == CPU_HW_PSTATE)
khz = find_khz_freq_from_fiddid(data->currfid, data->currdid); khz = find_khz_freq_from_pstate(data->powernow_table, data->currpstate);
else else
khz = find_khz_freq_from_fid(data->currfid); khz = find_khz_freq_from_fid(data->currfid);
......
...@@ -10,6 +10,7 @@ struct powernow_k8_data { ...@@ -10,6 +10,7 @@ struct powernow_k8_data {
u32 numps; /* number of p-states */ u32 numps; /* number of p-states */
u32 batps; /* number of p-states supported on battery */ u32 batps; /* number of p-states supported on battery */
u32 max_hw_pstate; /* maximum legal hardware pstate */
/* these values are constant when the PSB is used to determine /* these values are constant when the PSB is used to determine
* vid/fid pairings, but are modified during the ->target() call * vid/fid pairings, but are modified during the ->target() call
...@@ -21,8 +22,8 @@ struct powernow_k8_data { ...@@ -21,8 +22,8 @@ struct powernow_k8_data {
u32 plllock; /* pll lock time, units 1 us */ u32 plllock; /* pll lock time, units 1 us */
u32 exttype; /* extended interface = 1 */ u32 exttype; /* extended interface = 1 */
/* keep track of the current fid / vid or did */ /* keep track of the current fid / vid or pstate */
u32 currvid, currfid, currdid; u32 currvid, currfid, currpstate;
/* the powernow_table includes all frequency and vid/fid pairings: /* the powernow_table includes all frequency and vid/fid pairings:
* fid are the lower 8 bits of the index, vid are the upper 8 bits. * fid are the lower 8 bits of the index, vid are the upper 8 bits.
...@@ -87,23 +88,14 @@ struct powernow_k8_data { ...@@ -87,23 +88,14 @@ struct powernow_k8_data {
/* Hardware Pstate _PSS and MSR definitions */ /* Hardware Pstate _PSS and MSR definitions */
#define USE_HW_PSTATE 0x00000080 #define USE_HW_PSTATE 0x00000080
#define HW_PSTATE_FID_MASK 0x0000003f
#define HW_PSTATE_DID_MASK 0x000001c0
#define HW_PSTATE_DID_SHIFT 6
#define HW_PSTATE_MASK 0x00000007 #define HW_PSTATE_MASK 0x00000007
#define HW_PSTATE_VALID_MASK 0x80000000 #define HW_PSTATE_VALID_MASK 0x80000000
#define HW_FID_INDEX_SHIFT 8 #define HW_PSTATE_MAX_MASK 0x000000f0
#define HW_FID_INDEX_MASK 0x0000ff00 #define HW_PSTATE_MAX_SHIFT 4
#define HW_DID_INDEX_SHIFT 16
#define HW_DID_INDEX_MASK 0x00ff0000
#define HW_WATTS_MASK 0xff
#define HW_PWR_DVR_MASK 0x300
#define HW_PWR_DVR_SHIFT 8
#define HW_PWR_MAX_MULT 3
#define MAX_HW_PSTATE 8 /* hw pstate supports up to 8 */
#define MSR_PSTATE_DEF_BASE 0xc0010064 /* base of Pstate MSRs */ #define MSR_PSTATE_DEF_BASE 0xc0010064 /* base of Pstate MSRs */
#define MSR_PSTATE_STATUS 0xc0010063 /* Pstate Status MSR */ #define MSR_PSTATE_STATUS 0xc0010063 /* Pstate Status MSR */
#define MSR_PSTATE_CTRL 0xc0010062 /* Pstate control MSR */ #define MSR_PSTATE_CTRL 0xc0010062 /* Pstate control MSR */
#define MSR_PSTATE_CUR_LIMIT 0xc0010061 /* pstate current limit MSR */
/* define the two driver architectures */ /* define the two driver architectures */
#define CPU_OPTERON 0 #define CPU_OPTERON 0
......
...@@ -116,6 +116,27 @@ static inline unsigned int get_cpu_idle_time(unsigned int cpu) ...@@ -116,6 +116,27 @@ static inline unsigned int get_cpu_idle_time(unsigned int cpu)
return ret; return ret;
} }
/* keep track of frequency transitions */
static int
dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
struct cpufreq_freqs *freq = data;
struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cpu_dbs_info,
freq->cpu);
if (!this_dbs_info->enable)
return 0;
this_dbs_info->requested_freq = freq->new;
return 0;
}
static struct notifier_block dbs_cpufreq_notifier_block = {
.notifier_call = dbs_cpufreq_notifier
};
/************************** sysfs interface ************************/ /************************** sysfs interface ************************/
static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
{ {
...@@ -229,15 +250,15 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, ...@@ -229,15 +250,15 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
unsigned int j; unsigned int j;
ret = sscanf (buf, "%u", &input); ret = sscanf(buf, "%u", &input);
if ( ret != 1 ) if (ret != 1)
return -EINVAL; return -EINVAL;
if ( input > 1 ) if (input > 1)
input = 1; input = 1;
mutex_lock(&dbs_mutex); mutex_lock(&dbs_mutex);
if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */ if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */
mutex_unlock(&dbs_mutex); mutex_unlock(&dbs_mutex);
return count; return count;
} }
...@@ -261,12 +282,12 @@ static ssize_t store_freq_step(struct cpufreq_policy *policy, ...@@ -261,12 +282,12 @@ static ssize_t store_freq_step(struct cpufreq_policy *policy,
unsigned int input; unsigned int input;
int ret; int ret;
ret = sscanf (buf, "%u", &input); ret = sscanf(buf, "%u", &input);
if ( ret != 1 ) if (ret != 1)
return -EINVAL; return -EINVAL;
if ( input > 100 ) if (input > 100)
input = 100; input = 100;
/* no need to test here if freq_step is zero as the user might actually /* no need to test here if freq_step is zero as the user might actually
...@@ -462,8 +483,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, ...@@ -462,8 +483,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
switch (event) { switch (event) {
case CPUFREQ_GOV_START: case CPUFREQ_GOV_START:
if ((!cpu_online(cpu)) || if ((!cpu_online(cpu)) || (!policy->cur))
(!policy->cur))
return -EINVAL; return -EINVAL;
if (this_dbs_info->enable) /* Already enabled */ if (this_dbs_info->enable) /* Already enabled */
...@@ -511,6 +531,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, ...@@ -511,6 +531,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
dbs_tuners_ins.sampling_rate = def_sampling_rate; dbs_tuners_ins.sampling_rate = def_sampling_rate;
dbs_timer_init(); dbs_timer_init();
cpufreq_register_notifier(
&dbs_cpufreq_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER);
} }
mutex_unlock(&dbs_mutex); mutex_unlock(&dbs_mutex);
...@@ -525,8 +548,12 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, ...@@ -525,8 +548,12 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
* Stop the timerschedule work, when this governor * Stop the timerschedule work, when this governor
* is used for first time * is used for first time
*/ */
if (dbs_enable == 0) if (dbs_enable == 0) {
dbs_timer_exit(); dbs_timer_exit();
cpufreq_unregister_notifier(
&dbs_cpufreq_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER);
}
mutex_unlock(&dbs_mutex); mutex_unlock(&dbs_mutex);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册