aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/processor_throttling.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/processor_throttling.c')
-rw-r--r--drivers/acpi/processor_throttling.c76
1 files changed, 34 insertions, 42 deletions
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index e7dd2c1fee79..84243c32e29c 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -32,14 +32,11 @@
32#include <linux/init.h> 32#include <linux/init.h>
33#include <linux/sched.h> 33#include <linux/sched.h>
34#include <linux/cpufreq.h> 34#include <linux/cpufreq.h>
35 35#include <linux/acpi.h>
36#include <acpi/processor.h>
36#include <asm/io.h> 37#include <asm/io.h>
37#include <asm/uaccess.h> 38#include <asm/uaccess.h>
38 39
39#include <acpi/acpi_bus.h>
40#include <acpi/acpi_drivers.h>
41#include <acpi/processor.h>
42
43#define PREFIX "ACPI: " 40#define PREFIX "ACPI: "
44 41
45#define ACPI_PROCESSOR_CLASS "processor" 42#define ACPI_PROCESSOR_CLASS "processor"
@@ -59,6 +56,12 @@ struct throttling_tstate {
59 int target_state; /* target T-state */ 56 int target_state; /* target T-state */
60}; 57};
61 58
59struct acpi_processor_throttling_arg {
60 struct acpi_processor *pr;
61 int target_state;
62 bool force;
63};
64
62#define THROTTLING_PRECHANGE (1) 65#define THROTTLING_PRECHANGE (1)
63#define THROTTLING_POSTCHANGE (2) 66#define THROTTLING_POSTCHANGE (2)
64 67
@@ -1063,16 +1066,24 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
1063 return 0; 1066 return 0;
1064} 1067}
1065 1068
1069static long acpi_processor_throttling_fn(void *data)
1070{
1071 struct acpi_processor_throttling_arg *arg = data;
1072 struct acpi_processor *pr = arg->pr;
1073
1074 return pr->throttling.acpi_processor_set_throttling(pr,
1075 arg->target_state, arg->force);
1076}
1077
1066int acpi_processor_set_throttling(struct acpi_processor *pr, 1078int acpi_processor_set_throttling(struct acpi_processor *pr,
1067 int state, bool force) 1079 int state, bool force)
1068{ 1080{
1069 cpumask_var_t saved_mask;
1070 int ret = 0; 1081 int ret = 0;
1071 unsigned int i; 1082 unsigned int i;
1072 struct acpi_processor *match_pr; 1083 struct acpi_processor *match_pr;
1073 struct acpi_processor_throttling *p_throttling; 1084 struct acpi_processor_throttling *p_throttling;
1085 struct acpi_processor_throttling_arg arg;
1074 struct throttling_tstate t_state; 1086 struct throttling_tstate t_state;
1075 cpumask_var_t online_throttling_cpus;
1076 1087
1077 if (!pr) 1088 if (!pr)
1078 return -EINVAL; 1089 return -EINVAL;
@@ -1083,14 +1094,6 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
1083 if ((state < 0) || (state > (pr->throttling.state_count - 1))) 1094 if ((state < 0) || (state > (pr->throttling.state_count - 1)))
1084 return -EINVAL; 1095 return -EINVAL;
1085 1096
1086 if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
1087 return -ENOMEM;
1088
1089 if (!alloc_cpumask_var(&online_throttling_cpus, GFP_KERNEL)) {
1090 free_cpumask_var(saved_mask);
1091 return -ENOMEM;
1092 }
1093
1094 if (cpu_is_offline(pr->id)) { 1097 if (cpu_is_offline(pr->id)) {
1095 /* 1098 /*
1096 * the cpu pointed by pr->id is offline. Unnecessary to change 1099 * the cpu pointed by pr->id is offline. Unnecessary to change
@@ -1099,17 +1102,15 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
1099 return -ENODEV; 1102 return -ENODEV;
1100 } 1103 }
1101 1104
1102 cpumask_copy(saved_mask, &current->cpus_allowed);
1103 t_state.target_state = state; 1105 t_state.target_state = state;
1104 p_throttling = &(pr->throttling); 1106 p_throttling = &(pr->throttling);
1105 cpumask_and(online_throttling_cpus, cpu_online_mask, 1107
1106 p_throttling->shared_cpu_map);
1107 /* 1108 /*
1108 * The throttling notifier will be called for every 1109 * The throttling notifier will be called for every
1109 * affected cpu in order to get one proper T-state. 1110 * affected cpu in order to get one proper T-state.
1110 * The notifier event is THROTTLING_PRECHANGE. 1111 * The notifier event is THROTTLING_PRECHANGE.
1111 */ 1112 */
1112 for_each_cpu(i, online_throttling_cpus) { 1113 for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) {
1113 t_state.cpu = i; 1114 t_state.cpu = i;
1114 acpi_processor_throttling_notifier(THROTTLING_PRECHANGE, 1115 acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
1115 &t_state); 1116 &t_state);
@@ -1121,21 +1122,18 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
1121 * it can be called only for the cpu pointed by pr. 1122 * it can be called only for the cpu pointed by pr.
1122 */ 1123 */
1123 if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) { 1124 if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
1124 /* FIXME: use work_on_cpu() */ 1125 arg.pr = pr;
1125 if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) { 1126 arg.target_state = state;
1126 /* Can't migrate to the pr->id CPU. Exit */ 1127 arg.force = force;
1127 ret = -ENODEV; 1128 ret = work_on_cpu(pr->id, acpi_processor_throttling_fn, &arg);
1128 goto exit;
1129 }
1130 ret = p_throttling->acpi_processor_set_throttling(pr,
1131 t_state.target_state, force);
1132 } else { 1129 } else {
1133 /* 1130 /*
1134 * When the T-state coordination is SW_ALL or HW_ALL, 1131 * When the T-state coordination is SW_ALL or HW_ALL,
1135 * it is necessary to set T-state for every affected 1132 * it is necessary to set T-state for every affected
1136 * cpus. 1133 * cpus.
1137 */ 1134 */
1138 for_each_cpu(i, online_throttling_cpus) { 1135 for_each_cpu_and(i, cpu_online_mask,
1136 p_throttling->shared_cpu_map) {
1139 match_pr = per_cpu(processors, i); 1137 match_pr = per_cpu(processors, i);
1140 /* 1138 /*
1141 * If the pointer is invalid, we will report the 1139 * If the pointer is invalid, we will report the
@@ -1156,13 +1154,12 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
1156 "on CPU %d\n", i)); 1154 "on CPU %d\n", i));
1157 continue; 1155 continue;
1158 } 1156 }
1159 t_state.cpu = i; 1157
1160 /* FIXME: use work_on_cpu() */ 1158 arg.pr = match_pr;
1161 if (set_cpus_allowed_ptr(current, cpumask_of(i))) 1159 arg.target_state = state;
1162 continue; 1160 arg.force = force;
1163 ret = match_pr->throttling. 1161 ret = work_on_cpu(pr->id, acpi_processor_throttling_fn,
1164 acpi_processor_set_throttling( 1162 &arg);
1165 match_pr, t_state.target_state, force);
1166 } 1163 }
1167 } 1164 }
1168 /* 1165 /*
@@ -1171,17 +1168,12 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
1171 * affected cpu to update the T-states. 1168 * affected cpu to update the T-states.
1172 * The notifier event is THROTTLING_POSTCHANGE 1169 * The notifier event is THROTTLING_POSTCHANGE
1173 */ 1170 */
1174 for_each_cpu(i, online_throttling_cpus) { 1171 for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) {
1175 t_state.cpu = i; 1172 t_state.cpu = i;
1176 acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE, 1173 acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
1177 &t_state); 1174 &t_state);
1178 } 1175 }
1179 /* restore the previous state */ 1176
1180 /* FIXME: use work_on_cpu() */
1181 set_cpus_allowed_ptr(current, saved_mask);
1182exit:
1183 free_cpumask_var(online_throttling_cpus);
1184 free_cpumask_var(saved_mask);
1185 return ret; 1177 return ret;
1186} 1178}
1187 1179