diff options
Diffstat (limited to 'drivers/cpufreq/intel_pstate.c')
| -rw-r--r-- | drivers/cpufreq/intel_pstate.c | 66 | 
1 files changed, 39 insertions, 27 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 096fde0ebcb..ad72922919e 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -358,14 +358,14 @@ static void intel_pstate_sysfs_expose_params(void)  static int intel_pstate_min_pstate(void)  {  	u64 value; -	rdmsrl(0xCE, value); +	rdmsrl(MSR_PLATFORM_INFO, value);  	return (value >> 40) & 0xFF;  }  static int intel_pstate_max_pstate(void)  {  	u64 value; -	rdmsrl(0xCE, value); +	rdmsrl(MSR_PLATFORM_INFO, value);  	return (value >> 8) & 0xFF;  } @@ -373,7 +373,7 @@ static int intel_pstate_turbo_pstate(void)  {  	u64 value;  	int nont, ret; -	rdmsrl(0x1AD, value); +	rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value);  	nont = intel_pstate_max_pstate();  	ret = ((value) & 255);  	if (ret <= nont) @@ -454,7 +454,7 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu,  					sample->idletime_us * 100,  					sample->duration_us);  	core_pct = div64_u64(sample->aperf * 100, sample->mperf); -	sample->freq = cpu->pstate.turbo_pstate * core_pct * 1000; +	sample->freq = cpu->pstate.max_pstate * core_pct * 1000;  	sample->core_pct_busy = div_s64((sample->pstate_pct_busy * core_pct),  					100); @@ -662,6 +662,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)  	cpu = all_cpu_data[policy->cpu]; +	if (!policy->cpuinfo.max_freq) +		return -ENODEV; +  	intel_pstate_get_min_max(cpu, &min, &max);  	limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; @@ -747,37 +750,34 @@ static struct cpufreq_driver intel_pstate_driver = {  	.owner		= THIS_MODULE,  }; -static void intel_pstate_exit(void) +static int __initdata no_load; + +static int intel_pstate_msrs_not_valid(void)  { -	int cpu; +	/* Check that all the msr's we are using are valid. */ +	u64 aperf, mperf, tmp; -	sysfs_remove_group(intel_pstate_kobject, -				&intel_pstate_attr_group); -	debugfs_remove_recursive(debugfs_parent); +	rdmsrl(MSR_IA32_APERF, aperf); +	rdmsrl(MSR_IA32_MPERF, mperf); -	cpufreq_unregister_driver(&intel_pstate_driver); +	if (!intel_pstate_min_pstate() || +		!intel_pstate_max_pstate() || +		!intel_pstate_turbo_pstate()) +		return -ENODEV; -	if (!all_cpu_data) -		return; +	rdmsrl(MSR_IA32_APERF, tmp); +	if (!(tmp - aperf)) +		return -ENODEV; -	get_online_cpus(); -	for_each_online_cpu(cpu) { -		if (all_cpu_data[cpu]) { -			del_timer_sync(&all_cpu_data[cpu]->timer); -			kfree(all_cpu_data[cpu]); -		} -	} +	rdmsrl(MSR_IA32_MPERF, tmp); +	if (!(tmp - mperf)) +		return -ENODEV; -	put_online_cpus(); -	vfree(all_cpu_data); +	return 0;  } -module_exit(intel_pstate_exit); - -static int __initdata no_load; -  static int __init intel_pstate_init(void)  { -	int rc = 0; +	int cpu, rc = 0;  	const struct x86_cpu_id *id;  	if (no_load) @@ -787,6 +787,9 @@ static int __init intel_pstate_init(void)  	if (!id)  		return -ENODEV; +	if (intel_pstate_msrs_not_valid()) +		return -ENODEV; +  	pr_info("Intel P-state driver initializing.\n");  	all_cpu_data = vmalloc(sizeof(void *) * num_possible_cpus()); @@ -802,7 +805,16 @@ static int __init intel_pstate_init(void)  	intel_pstate_sysfs_expose_params();  	return rc;  out: -	intel_pstate_exit(); +	get_online_cpus(); +	for_each_online_cpu(cpu) { +		if (all_cpu_data[cpu]) { +			del_timer_sync(&all_cpu_data[cpu]->timer); +			kfree(all_cpu_data[cpu]); +		} +	} + +	put_online_cpus(); +	vfree(all_cpu_data);  	return -ENODEV;  }  device_initcall(intel_pstate_init);  |