diff options
author | Zhao Yakui <yakui.zhao@intel.com> | 2011-01-10 03:35:44 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2011-01-10 12:35:04 -0500 |
commit | daef1f35ea1e2cca125eecd5f078f40b55eb9105 (patch) | |
tree | ba3cfad2743cbd70a6d36dfe645c427a1634eeb1 | |
parent | 3c0eee3fe6a3a1c745379547c7e7c904aa64f6d5 (diff) |
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 ff3632717c51..ffc859c61393 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) | |||
876 | */ | 876 | */ |
877 | cpumask_copy(saved_mask, ¤t->cpus_allowed); | 877 | cpumask_copy(saved_mask, ¤t->cpus_allowed); |
878 | /* FIXME: use work_on_cpu() */ | 878 | /* FIXME: use work_on_cpu() */ |
879 | set_cpus_allowed_ptr(current, cpumask_of(pr->id)); | 879 | if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) { |
880 | /* Can't migrate to the target pr->id CPU. Exit */ | ||
881 | free_cpumask_var(saved_mask); | ||
882 | return -ENODEV; | ||
883 | } | ||
880 | ret = pr->throttling.acpi_processor_get_throttling(pr); | 884 | ret = pr->throttling.acpi_processor_get_throttling(pr); |
881 | /* restore the previous state */ | 885 | /* restore the previous state */ |
882 | set_cpus_allowed_ptr(current, saved_mask); | 886 | set_cpus_allowed_ptr(current, saved_mask); |
@@ -1051,6 +1055,14 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, | |||
1051 | return -ENOMEM; | 1055 | return -ENOMEM; |
1052 | } | 1056 | } |
1053 | 1057 | ||
1058 | if (cpu_is_offline(pr->id)) { | ||
1059 | /* | ||
1060 | * the cpu pointed by pr->id is offline. Unnecessary to change | ||
1061 | * the throttling state any more. | ||
1062 | */ | ||
1063 | return -ENODEV; | ||
1064 | } | ||
1065 | |||
1054 | cpumask_copy(saved_mask, ¤t->cpus_allowed); | 1066 | cpumask_copy(saved_mask, ¤t->cpus_allowed); |
1055 | t_state.target_state = state; | 1067 | t_state.target_state = state; |
1056 | p_throttling = &(pr->throttling); | 1068 | p_throttling = &(pr->throttling); |
@@ -1074,7 +1086,11 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, | |||
1074 | */ | 1086 | */ |
1075 | if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) { | 1087 | if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) { |
1076 | /* FIXME: use work_on_cpu() */ | 1088 | /* FIXME: use work_on_cpu() */ |
1077 | set_cpus_allowed_ptr(current, cpumask_of(pr->id)); | 1089 | if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) { |
1090 | /* Can't migrate to the pr->id CPU. Exit */ | ||
1091 | ret = -ENODEV; | ||
1092 | goto exit; | ||
1093 | } | ||
1078 | ret = p_throttling->acpi_processor_set_throttling(pr, | 1094 | ret = p_throttling->acpi_processor_set_throttling(pr, |
1079 | t_state.target_state, force); | 1095 | t_state.target_state, force); |
1080 | } else { | 1096 | } else { |
@@ -1106,7 +1122,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, | |||
1106 | } | 1122 | } |
1107 | t_state.cpu = i; | 1123 | t_state.cpu = i; |
1108 | /* FIXME: use work_on_cpu() */ | 1124 | /* FIXME: use work_on_cpu() */ |
1109 | set_cpus_allowed_ptr(current, cpumask_of(i)); | 1125 | if (set_cpus_allowed_ptr(current, cpumask_of(i))) |
1126 | continue; | ||
1110 | ret = match_pr->throttling. | 1127 | ret = match_pr->throttling. |
1111 | acpi_processor_set_throttling( | 1128 | acpi_processor_set_throttling( |
1112 | match_pr, t_state.target_state, force); | 1129 | match_pr, t_state.target_state, force); |
@@ -1126,6 +1143,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, | |||
1126 | /* restore the previous state */ | 1143 | /* restore the previous state */ |
1127 | /* FIXME: use work_on_cpu() */ | 1144 | /* FIXME: use work_on_cpu() */ |
1128 | set_cpus_allowed_ptr(current, saved_mask); | 1145 | set_cpus_allowed_ptr(current, saved_mask); |
1146 | exit: | ||
1129 | free_cpumask_var(online_throttling_cpus); | 1147 | free_cpumask_var(online_throttling_cpus); |
1130 | free_cpumask_var(saved_mask); | 1148 | free_cpumask_var(saved_mask); |
1131 | return ret; | 1149 | return ret; |