diff options
| author | Zhao Yakui <yakui.zhao@intel.com> | 2011-01-10 16:35:44 +0800 | 
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2011-01-10 12:35:04 -0500 | 
| commit | daef1f35ea1e2cca125eecd5f078f40b55eb9105 (patch) | |
| tree | ba3cfad2743cbd70a6d36dfe645c427a1634eeb1 | |
| parent | 3c0eee3fe6a3a1c745379547c7e7c904aa64f6d5 (diff) | |
| download | olio-linux-3.10-daef1f35ea1e2cca125eecd5f078f40b55eb9105.tar.xz olio-linux-3.10-daef1f35ea1e2cca125eecd5f078f40b55eb9105.zip  | |
ACPI: Check the returned value of set_cpus_allowed_ptr before T-state operation
Now before it executes the T-state operation on one CPU, it will try to
migrate to the target CPU. Especially this is required on the system that
uses the MSR_IA32_THERMAL_CONTROL register to switch T-state.
But unfortunately it doesn't check whether the migration is successful or not.
In such case we will get/set the incorrect T-state on the offline CPU as
it fails in the migration to the offline CPU.
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
| -rw-r--r-- | drivers/acpi/processor_throttling.c | 24 | 
1 files changed, 21 insertions, 3 deletions
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index ff3632717c5..ffc859c6139 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -876,7 +876,11 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)  	 */  	cpumask_copy(saved_mask, ¤t->cpus_allowed);  	/* FIXME: use work_on_cpu() */ -	set_cpus_allowed_ptr(current, cpumask_of(pr->id)); +	if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) { +		/* Can't migrate to the target pr->id CPU. Exit */ +		free_cpumask_var(saved_mask); +		return -ENODEV; +	}  	ret = pr->throttling.acpi_processor_get_throttling(pr);  	/* restore the previous state */  	set_cpus_allowed_ptr(current, saved_mask); @@ -1051,6 +1055,14 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,  		return -ENOMEM;  	} +	if (cpu_is_offline(pr->id)) { +		/* +		 * the cpu pointed by pr->id is offline. Unnecessary to change +		 * the throttling state any more. +		 */ +		return -ENODEV; +	} +  	cpumask_copy(saved_mask, ¤t->cpus_allowed);  	t_state.target_state = state;  	p_throttling = &(pr->throttling); @@ -1074,7 +1086,11 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,  	 */  	if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {  		/* FIXME: use work_on_cpu() */ -		set_cpus_allowed_ptr(current, cpumask_of(pr->id)); +		if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) { +			/* Can't migrate to the pr->id CPU. Exit */ +			ret = -ENODEV; +			goto exit; +		}  		ret = p_throttling->acpi_processor_set_throttling(pr,  						t_state.target_state, force);  	} else { @@ -1106,7 +1122,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,  			}  			t_state.cpu = i;  			/* FIXME: use work_on_cpu() */ -			set_cpus_allowed_ptr(current, cpumask_of(i)); +			if (set_cpus_allowed_ptr(current, cpumask_of(i))) +				continue;  			ret = match_pr->throttling.  				acpi_processor_set_throttling(  				match_pr, t_state.target_state, force); @@ -1126,6 +1143,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,  	/* restore the previous state */  	/* FIXME: use work_on_cpu() */  	set_cpus_allowed_ptr(current, saved_mask); +exit:  	free_cpumask_var(online_throttling_cpus);  	free_cpumask_var(saved_mask);  	return ret;  |