Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4c5cdb1e authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 8c086340 18a7247d
Loading
Loading
Loading
Loading
+23 −67
Original line number Original line Diff line number Diff line
@@ -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)
	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)
	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,
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)
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
			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
/* 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
	}
	}


	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
	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
	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)
	    + (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)
	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)
		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);


+6 −14
Original line number Original line Diff line number Diff line
@@ -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 {
	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 {


/* 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
+90 −63
Original line number Original line Diff line number Diff line
@@ -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)
{
{
@@ -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,
			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,
		 * 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);