diff options
Diffstat (limited to 'drivers/cpufreq/acpi-cpufreq.c')
| -rw-r--r-- | drivers/cpufreq/acpi-cpufreq.c | 92 | 
1 files changed, 50 insertions, 42 deletions
| diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 0136dfcdabf0..798277227de7 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -65,18 +65,21 @@ enum {  #define MSR_K7_HWCR_CPB_DIS	(1ULL << 25)  struct acpi_cpufreq_data { -	struct acpi_processor_performance *acpi_data;  	struct cpufreq_frequency_table *freq_table;  	unsigned int resume;  	unsigned int cpu_feature; +	unsigned int acpi_perf_cpu;  	cpumask_var_t freqdomain_cpus;  }; -static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data); -  /* acpi_perf_data is a pointer to percpu data. */  static struct acpi_processor_performance __percpu *acpi_perf_data; +static inline struct acpi_processor_performance *to_perf_data(struct acpi_cpufreq_data *data) +{ +	return per_cpu_ptr(acpi_perf_data, data->acpi_perf_cpu); +} +  static struct cpufreq_driver acpi_cpufreq_driver;  static unsigned int acpi_pstate_strict; @@ -144,7 +147,7 @@ static int _store_boost(int val)  static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)  { -	struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); +	struct acpi_cpufreq_data *data = policy->driver_data;  	return cpufreq_show_cpus(data->freqdomain_cpus, buf);  } @@ -202,7 +205,7 @@ static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data)  	struct acpi_processor_performance *perf;  	int i; -	perf = data->acpi_data; +	perf = to_perf_data(data);  	for (i = 0; i < perf->state_count; i++) {  		if (value == perf->states[i].status) @@ -221,7 +224,7 @@ static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)  	else  		msr &= INTEL_MSR_RANGE; -	perf = data->acpi_data; +	perf = to_perf_data(data);  	cpufreq_for_each_entry(pos, data->freq_table)  		if (msr == perf->states[pos->driver_data].status) @@ -327,7 +330,8 @@ static void drv_write(struct drv_cmd *cmd)  	put_cpu();  } -static u32 get_cur_val(const struct cpumask *mask) +static u32 +get_cur_val(const struct cpumask *mask, struct acpi_cpufreq_data *data)  {  	struct acpi_processor_performance *perf;  	struct drv_cmd cmd; @@ -335,7 +339,7 @@ static u32 get_cur_val(const struct cpumask *mask)  	if (unlikely(cpumask_empty(mask)))  		return 0; -	switch (per_cpu(acfreq_data, cpumask_first(mask))->cpu_feature) { +	switch (data->cpu_feature) {  	case SYSTEM_INTEL_MSR_CAPABLE:  		cmd.type = SYSTEM_INTEL_MSR_CAPABLE;  		cmd.addr.msr.reg = MSR_IA32_PERF_CTL; @@ -346,7 +350,7 @@ static u32 get_cur_val(const struct cpumask *mask)  		break;  	case SYSTEM_IO_CAPABLE:  		cmd.type = SYSTEM_IO_CAPABLE; -		perf = per_cpu(acfreq_data, cpumask_first(mask))->acpi_data; +		perf = to_perf_data(data);  		cmd.addr.io.port = perf->control_register.address;  		cmd.addr.io.bit_width = perf->control_register.bit_width;  		break; @@ -364,19 +368,23 @@ static u32 get_cur_val(const struct cpumask *mask)  static unsigned int get_cur_freq_on_cpu(unsigned int cpu)  { -	struct acpi_cpufreq_data *data = per_cpu(acfreq_data, cpu); +	struct acpi_cpufreq_data *data; +	struct cpufreq_policy *policy;  	unsigned int freq;  	unsigned int cached_freq;  	pr_debug("get_cur_freq_on_cpu (%d)\n", cpu); -	if (unlikely(data == NULL || -		     data->acpi_data == NULL || data->freq_table == NULL)) { +	policy = cpufreq_cpu_get_raw(cpu); +	if (unlikely(!policy))  		return 0; -	} -	cached_freq = data->freq_table[data->acpi_data->state].frequency; -	freq = extract_freq(get_cur_val(cpumask_of(cpu)), data); +	data = policy->driver_data; +	if (unlikely(!data || !data->freq_table)) +		return 0; + +	cached_freq = data->freq_table[to_perf_data(data)->state].frequency; +	freq = extract_freq(get_cur_val(cpumask_of(cpu), data), data);  	if (freq != cached_freq) {  		/*  		 * The dreaded BIOS frequency change behind our back. @@ -397,7 +405,7 @@ static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq,  	unsigned int i;  	for (i = 0; i < 100; i++) { -		cur_freq = extract_freq(get_cur_val(mask), data); +		cur_freq = extract_freq(get_cur_val(mask, data), data);  		if (cur_freq == freq)  			return 1;  		udelay(10); @@ -408,18 +416,17 @@ static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq,  static int acpi_cpufreq_target(struct cpufreq_policy *policy,  			       unsigned int index)  { -	struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); +	struct acpi_cpufreq_data *data = policy->driver_data;  	struct acpi_processor_performance *perf;  	struct drv_cmd cmd;  	unsigned int next_perf_state = 0; /* Index into perf table */  	int result = 0; -	if (unlikely(data == NULL || -	     data->acpi_data == NULL || data->freq_table == NULL)) { +	if (unlikely(data == NULL || data->freq_table == NULL)) {  		return -ENODEV;  	} -	perf = data->acpi_data; +	perf = to_perf_data(data);  	next_perf_state = data->freq_table[index].driver_data;  	if (perf->state == next_perf_state) {  		if (unlikely(data->resume)) { @@ -482,8 +489,9 @@ out:  static unsigned long  acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)  { -	struct acpi_processor_performance *perf = data->acpi_data; +	struct acpi_processor_performance *perf; +	perf = to_perf_data(data);  	if (cpu_khz) {  		/* search the closest match to cpu_khz */  		unsigned int i; @@ -672,17 +680,17 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)  		goto err_free;  	} -	data->acpi_data = per_cpu_ptr(acpi_perf_data, cpu); -	per_cpu(acfreq_data, cpu) = data; +	perf = per_cpu_ptr(acpi_perf_data, cpu); +	data->acpi_perf_cpu = cpu; +	policy->driver_data = data;  	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC))  		acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; -	result = acpi_processor_register_performance(data->acpi_data, cpu); +	result = acpi_processor_register_performance(perf, cpu);  	if (result)  		goto err_free_mask; -	perf = data->acpi_data;  	policy->shared_type = perf->shared_type;  	/* @@ -838,26 +846,25 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)  err_freqfree:  	kfree(data->freq_table);  err_unreg: -	acpi_processor_unregister_performance(perf, cpu); +	acpi_processor_unregister_performance(cpu);  err_free_mask:  	free_cpumask_var(data->freqdomain_cpus);  err_free:  	kfree(data); -	per_cpu(acfreq_data, cpu) = NULL; +	policy->driver_data = NULL;  	return result;  }  static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)  { -	struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); +	struct acpi_cpufreq_data *data = policy->driver_data;  	pr_debug("acpi_cpufreq_cpu_exit\n");  	if (data) { -		per_cpu(acfreq_data, policy->cpu) = NULL; -		acpi_processor_unregister_performance(data->acpi_data, -						      policy->cpu); +		policy->driver_data = NULL; +		acpi_processor_unregister_performance(data->acpi_perf_cpu);  		free_cpumask_var(data->freqdomain_cpus);  		kfree(data->freq_table);  		kfree(data); @@ -868,7 +875,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)  static int acpi_cpufreq_resume(struct cpufreq_policy *policy)  { -	struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu); +	struct acpi_cpufreq_data *data = policy->driver_data;  	pr_debug("acpi_cpufreq_resume\n"); @@ -880,7 +887,9 @@ static int acpi_cpufreq_resume(struct cpufreq_policy *policy)  static struct freq_attr *acpi_cpufreq_attr[] = {  	&cpufreq_freq_attr_scaling_available_freqs,  	&freqdomain_cpus, -	NULL,	/* this is a placeholder for cpb, do not remove */ +#ifdef CONFIG_X86_ACPI_CPUFREQ_CPB +	&cpb, +#endif  	NULL,  }; @@ -953,17 +962,16 @@ static int __init acpi_cpufreq_init(void)  	 * only if configured. This is considered legacy code, which  	 * will probably be removed at some point in the future.  	 */ -	if (check_amd_hwpstate_cpu(0)) { -		struct freq_attr **iter; - -		pr_debug("adding sysfs entry for cpb\n"); +	if (!check_amd_hwpstate_cpu(0)) { +		struct freq_attr **attr; -		for (iter = acpi_cpufreq_attr; *iter != NULL; iter++) -			; +		pr_debug("CPB unsupported, do not expose it\n"); -		/* make sure there is a terminator behind it */ -		if (iter[1] == NULL) -			*iter = &cpb; +		for (attr = acpi_cpufreq_attr; *attr; attr++) +			if (*attr == &cpb) { +				*attr = NULL; +				break; +			}  	}  #endif  	acpi_cpufreq_boost_init(); |