diff options
Diffstat (limited to 'drivers/cpufreq/acpi-cpufreq.c')
| -rw-r--r-- | drivers/cpufreq/acpi-cpufreq.c | 170 | 
1 files changed, 58 insertions, 112 deletions
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index d2c3253e015..b0c18ed8d83 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -80,7 +80,6 @@ static struct acpi_processor_performance __percpu *acpi_perf_data;  static struct cpufreq_driver acpi_cpufreq_driver;  static unsigned int acpi_pstate_strict; -static bool boost_enabled, boost_supported;  static struct msr __percpu *msrs;  static bool boost_state(unsigned int cpu) @@ -133,49 +132,16 @@ static void boost_set_msrs(bool enable, const struct cpumask *cpumask)  	wrmsr_on_cpus(cpumask, msr_addr, msrs);  } -static ssize_t _store_boost(const char *buf, size_t count) +static int _store_boost(int val)  { -	int ret; -	unsigned long val = 0; - -	if (!boost_supported) -		return -EINVAL; - -	ret = kstrtoul(buf, 10, &val); -	if (ret || (val > 1)) -		return -EINVAL; - -	if ((val && boost_enabled) || (!val && !boost_enabled)) -		return count; -  	get_online_cpus(); -  	boost_set_msrs(val, cpu_online_mask); -  	put_online_cpus(); - -	boost_enabled = val;  	pr_debug("Core Boosting %sabled.\n", val ? "en" : "dis"); -	return count; -} - -static ssize_t store_global_boost(struct kobject *kobj, struct attribute *attr, -				  const char *buf, size_t count) -{ -	return _store_boost(buf, count); -} - -static ssize_t show_global_boost(struct kobject *kobj, -				 struct attribute *attr, char *buf) -{ -	return sprintf(buf, "%u\n", boost_enabled); +	return 0;  } -static struct global_attr global_boost = __ATTR(boost, 0644, -						show_global_boost, -						store_global_boost); -  static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)  {  	struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); @@ -186,15 +152,32 @@ static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)  cpufreq_freq_attr_ro(freqdomain_cpus);  #ifdef CONFIG_X86_ACPI_CPUFREQ_CPB +static ssize_t store_boost(const char *buf, size_t count) +{ +	int ret; +	unsigned long val = 0; + +	if (!acpi_cpufreq_driver.boost_supported) +		return -EINVAL; + +	ret = kstrtoul(buf, 10, &val); +	if (ret || (val > 1)) +		return -EINVAL; + +	_store_boost((int) val); + +	return count; +} +  static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,  			 size_t count)  { -	return _store_boost(buf, count); +	return store_boost(buf, count);  }  static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf)  { -	return sprintf(buf, "%u\n", boost_enabled); +	return sprintf(buf, "%u\n", acpi_cpufreq_driver.boost_enabled);  }  cpufreq_freq_attr_rw(cpb); @@ -230,7 +213,7 @@ static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data)  static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)  { -	int i; +	struct cpufreq_frequency_table *pos;  	struct acpi_processor_performance *perf;  	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) @@ -240,10 +223,9 @@ static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)  	perf = data->acpi_data; -	for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { -		if (msr == perf->states[data->freq_table[i].driver_data].status) -			return data->freq_table[i].frequency; -	} +	cpufreq_for_each_entry(pos, data->freq_table) +		if (msr == perf->states[pos->driver_data].status) +			return pos->frequency;  	return data->freq_table[0].frequency;  } @@ -424,34 +406,21 @@ static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq,  }  static int acpi_cpufreq_target(struct cpufreq_policy *policy, -			       unsigned int target_freq, unsigned int relation) +			       unsigned int index)  {  	struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);  	struct acpi_processor_performance *perf; -	struct cpufreq_freqs freqs;  	struct drv_cmd cmd; -	unsigned int next_state = 0; /* Index into freq_table */  	unsigned int next_perf_state = 0; /* Index into perf table */  	int result = 0; -	pr_debug("acpi_cpufreq_target %d (%d)\n", target_freq, policy->cpu); -  	if (unlikely(data == NULL ||  	     data->acpi_data == NULL || data->freq_table == NULL)) {  		return -ENODEV;  	}  	perf = data->acpi_data; -	result = cpufreq_frequency_table_target(policy, -						data->freq_table, -						target_freq, -						relation, &next_state); -	if (unlikely(result)) { -		result = -ENODEV; -		goto out; -	} - -	next_perf_state = data->freq_table[next_state].driver_data; +	next_perf_state = data->freq_table[index].driver_data;  	if (perf->state == next_perf_state) {  		if (unlikely(data->resume)) {  			pr_debug("Called after resume, resetting to P%d\n", @@ -492,23 +461,17 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,  	else  		cmd.mask = cpumask_of(policy->cpu); -	freqs.old = perf->states[perf->state].core_frequency * 1000; -	freqs.new = data->freq_table[next_state].frequency; -	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); -  	drv_write(&cmd);  	if (acpi_pstate_strict) { -		if (!check_freqs(cmd.mask, freqs.new, data)) { +		if (!check_freqs(cmd.mask, data->freq_table[index].frequency, +					data)) {  			pr_debug("acpi_cpufreq_target failed (%d)\n",  				policy->cpu);  			result = -EAGAIN; -			freqs.new = freqs.old;  		}  	} -	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); -  	if (!result)  		perf->state = next_perf_state; @@ -516,15 +479,6 @@ out:  	return result;  } -static int acpi_cpufreq_verify(struct cpufreq_policy *policy) -{ -	struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); - -	pr_debug("acpi_cpufreq_verify\n"); - -	return cpufreq_frequency_table_verify(policy, data->freq_table); -} -  static unsigned long  acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)  { @@ -582,7 +536,7 @@ static int boost_notify(struct notifier_block *nb, unsigned long action,  	switch (action) {  	case CPU_UP_PREPARE:  	case CPU_UP_PREPARE_FROZEN: -		boost_set_msrs(boost_enabled, cpumask); +		boost_set_msrs(acpi_cpufreq_driver.boost_enabled, cpumask);  		break;  	case CPU_DOWN_PREPARE: @@ -799,7 +753,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)  		goto err_unreg;  	} -	data->freq_table = kmalloc(sizeof(*data->freq_table) * +	data->freq_table = kzalloc(sizeof(*data->freq_table) *  		    (perf->state_count+1), GFP_KERNEL);  	if (!data->freq_table) {  		result = -ENOMEM; @@ -837,7 +791,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)  	data->freq_table[valid_states].frequency = CPUFREQ_TABLE_END;  	perf->state = 0; -	result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table); +	result = cpufreq_table_validate_and_show(policy, data->freq_table);  	if (result)  		goto err_freqfree; @@ -846,12 +800,16 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)  	switch (perf->control_register.space_id) {  	case ACPI_ADR_SPACE_SYSTEM_IO: -		/* Current speed is unknown and not detectable by IO port */ +		/* +		 * The core will not set policy->cur, because +		 * cpufreq_driver->get is NULL, so we need to set it here. +		 * However, we have to guess it, because the current speed is +		 * unknown and not detectable via IO ports. +		 */  		policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);  		break;  	case ACPI_ADR_SPACE_FIXED_HARDWARE:  		acpi_cpufreq_driver.get = get_cur_freq_on_cpu; -		policy->cur = get_cur_freq_on_cpu(cpu);  		break;  	default:  		break; @@ -868,8 +826,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)  			(u32) perf->states[i].power,  			(u32) perf->states[i].transition_latency); -	cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu); -  	/*  	 * the first call to ->target() should result in us actually  	 * writing something to the appropriate registers. @@ -898,7 +854,6 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)  	pr_debug("acpi_cpufreq_cpu_exit\n");  	if (data) { -		cpufreq_frequency_table_put_attr(policy->cpu);  		per_cpu(acfreq_data, policy->cpu) = NULL;  		acpi_processor_unregister_performance(data->acpi_data,  						      policy->cpu); @@ -929,14 +884,15 @@ static struct freq_attr *acpi_cpufreq_attr[] = {  };  static struct cpufreq_driver acpi_cpufreq_driver = { -	.verify		= acpi_cpufreq_verify, -	.target		= acpi_cpufreq_target, +	.verify		= cpufreq_generic_frequency_table_verify, +	.target_index	= acpi_cpufreq_target,  	.bios_limit	= acpi_processor_get_bios_limit,  	.init		= acpi_cpufreq_cpu_init,  	.exit		= acpi_cpufreq_cpu_exit,  	.resume		= acpi_cpufreq_resume,  	.name		= "acpi-cpufreq",  	.attr		= acpi_cpufreq_attr, +	.set_boost      = _store_boost,  };  static void __init acpi_cpufreq_boost_init(void) @@ -947,33 +903,23 @@ static void __init acpi_cpufreq_boost_init(void)  		if (!msrs)  			return; -		boost_supported = true; -		boost_enabled = boost_state(0); +		acpi_cpufreq_driver.boost_supported = true; +		acpi_cpufreq_driver.boost_enabled = boost_state(0); -		get_online_cpus(); +		cpu_notifier_register_begin();  		/* Force all MSRs to the same value */ -		boost_set_msrs(boost_enabled, cpu_online_mask); - -		register_cpu_notifier(&boost_nb); +		boost_set_msrs(acpi_cpufreq_driver.boost_enabled, +			       cpu_online_mask); -		put_online_cpus(); -	} else -		global_boost.attr.mode = 0444; +		__register_cpu_notifier(&boost_nb); -	/* We create the boost file in any case, though for systems without -	 * hardware support it will be read-only and hardwired to return 0. -	 */ -	if (cpufreq_sysfs_create_file(&(global_boost.attr))) -		pr_warn(PFX "could not register global boost sysfs file\n"); -	else -		pr_debug("registered global boost sysfs file\n"); +		cpu_notifier_register_done(); +	}  } -static void __exit acpi_cpufreq_boost_exit(void) +static void acpi_cpufreq_boost_exit(void)  { -	cpufreq_sysfs_remove_file(&(global_boost.attr)); -  	if (msrs) {  		unregister_cpu_notifier(&boost_nb); @@ -986,12 +932,12 @@ static int __init acpi_cpufreq_init(void)  {  	int ret; +	if (acpi_disabled) +		return -ENODEV; +  	/* don't keep reloading if cpufreq_driver exists */  	if (cpufreq_get_current_driver()) -		return 0; - -	if (acpi_disabled) -		return 0; +		return -EEXIST;  	pr_debug("acpi_cpufreq_init\n"); @@ -1019,13 +965,13 @@ static int __init acpi_cpufreq_init(void)  			*iter = &cpb;  	}  #endif +	acpi_cpufreq_boost_init();  	ret = cpufreq_register_driver(&acpi_cpufreq_driver); -	if (ret) +	if (ret) {  		free_acpi_perf_data(); -	else -		acpi_cpufreq_boost_init(); - +		acpi_cpufreq_boost_exit(); +	}  	return ret;  }  | 
