diff options
Diffstat (limited to 'drivers/acpi/processor_thermal.c')
| -rw-r--r-- | drivers/acpi/processor_thermal.c | 104 | 
1 files changed, 60 insertions, 44 deletions
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index fde49b9b1d9..e003663b2f8 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -30,13 +30,9 @@  #include <linux/module.h>  #include <linux/init.h>  #include <linux/cpufreq.h> -#include <linux/sysdev.h> - -#include <asm/uaccess.h> - -#include <acpi/acpi_bus.h> +#include <linux/acpi.h>  #include <acpi/processor.h> -#include <acpi/acpi_drivers.h> +#include <asm/uaccess.h>  #define PREFIX "ACPI: " @@ -58,6 +54,27 @@ ACPI_MODULE_NAME("processor_thermal");  static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg);  static unsigned int acpi_thermal_cpufreq_is_init = 0; +#define reduction_pctg(cpu) \ +	per_cpu(cpufreq_thermal_reduction_pctg, phys_package_first_cpu(cpu)) + +/* + * Emulate "per package data" using per cpu data (which should really be + * provided elsewhere) + * + * Note we can lose a CPU on cpu hotunplug, in this case we forget the state + * temporarily. Fortunately that's not a big issue here (I hope) + */ +static int phys_package_first_cpu(int cpu) +{ +	int i; +	int id = topology_physical_package_id(cpu); + +	for_each_online_cpu(i) +		if (topology_physical_package_id(i) == id) +			return i; +	return 0; +} +  static int cpu_has_cpufreq(unsigned int cpu)  {  	struct cpufreq_policy policy; @@ -77,7 +94,7 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,  	max_freq = (  	    policy->cpuinfo.max_freq * -	    (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20) +	    (100 - reduction_pctg(policy->cpu) * 20)  	) / 100;  	cpufreq_verify_within_limits(policy, 0, max_freq); @@ -103,16 +120,28 @@ static int cpufreq_get_cur_state(unsigned int cpu)  	if (!cpu_has_cpufreq(cpu))  		return 0; -	return per_cpu(cpufreq_thermal_reduction_pctg, cpu); +	return reduction_pctg(cpu);  }  static int cpufreq_set_cur_state(unsigned int cpu, int state)  { +	int i; +  	if (!cpu_has_cpufreq(cpu))  		return 0; -	per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state; -	cpufreq_update_policy(cpu); +	reduction_pctg(cpu) = state; + +	/* +	 * Update all the CPUs in the same package because they all +	 * contribute to the temperature and often share the same +	 * frequency. +	 */ +	for_each_online_cpu(i) { +		if (topology_physical_package_id(i) == +		    topology_physical_package_id(cpu)) +			cpufreq_update_policy(i); +	}  	return 0;  } @@ -120,10 +149,6 @@ void acpi_thermal_cpufreq_init(void)  {  	int i; -	for (i = 0; i < nr_cpu_ids; i++) -		if (cpu_present(i)) -			per_cpu(cpufreq_thermal_reduction_pctg, i) = 0; -  	i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block,  				      CPUFREQ_POLICY_NOTIFIER);  	if (!i) @@ -156,37 +181,16 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state)  	return 0;  } -static int acpi_thermal_cpufreq_increase(unsigned int cpu) -{ -	return -ENODEV; -} -static int acpi_thermal_cpufreq_decrease(unsigned int cpu) -{ -	return -ENODEV; -} -  #endif -int acpi_processor_get_limit_info(struct acpi_processor *pr) -{ - -	if (!pr) -		return -EINVAL; - -	if (pr->flags.throttling) -		pr->flags.limit = 1; - -	return 0; -} - -/* thermal coolign device callbacks */ +/* thermal cooling device callbacks */  static int acpi_processor_max_state(struct acpi_processor *pr)  {  	int max_state = 0;  	/*  	 * There exists four states according to -	 * cpufreq_thermal_reduction_ptg. 0, 1, 2, 3 +	 * cpufreq_thermal_reduction_pctg. 0, 1, 2, 3  	 */  	max_state += cpufreq_get_max_state(pr->id);  	if (pr->flags.throttling) @@ -199,9 +203,13 @@ processor_get_max_state(struct thermal_cooling_device *cdev,  			unsigned long *state)  {  	struct acpi_device *device = cdev->devdata; -	struct acpi_processor *pr = acpi_driver_data(device); +	struct acpi_processor *pr; + +	if (!device) +		return -EINVAL; -	if (!device || !pr) +	pr = acpi_driver_data(device); +	if (!pr)  		return -EINVAL;  	*state = acpi_processor_max_state(pr); @@ -213,9 +221,13 @@ processor_get_cur_state(struct thermal_cooling_device *cdev,  			unsigned long *cur_state)  {  	struct acpi_device *device = cdev->devdata; -	struct acpi_processor *pr = acpi_driver_data(device); +	struct acpi_processor *pr; -	if (!device || !pr) +	if (!device) +		return -EINVAL; + +	pr = acpi_driver_data(device); +	if (!pr)  		return -EINVAL;  	*cur_state = cpufreq_get_cur_state(pr->id); @@ -229,11 +241,15 @@ processor_set_cur_state(struct thermal_cooling_device *cdev,  			unsigned long state)  {  	struct acpi_device *device = cdev->devdata; -	struct acpi_processor *pr = acpi_driver_data(device); +	struct acpi_processor *pr;  	int result = 0;  	int max_pstate; -	if (!device || !pr) +	if (!device) +		return -EINVAL; + +	pr = acpi_driver_data(device); +	if (!pr)  		return -EINVAL;  	max_pstate = cpufreq_get_max_state(pr->id); @@ -253,7 +269,7 @@ processor_set_cur_state(struct thermal_cooling_device *cdev,  	return result;  } -struct thermal_cooling_device_ops processor_cooling_ops = { +const struct thermal_cooling_device_ops processor_cooling_ops = {  	.get_max_state = processor_get_max_state,  	.get_cur_state = processor_get_cur_state,  	.set_cur_state = processor_set_cur_state,  | 
