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.c220
1 files changed, 84 insertions, 136 deletions
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 730863855ed5..605a2954ef17 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -32,8 +32,6 @@
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#include <linux/proc_fs.h>
36#include <linux/seq_file.h>
37 35
38#include <asm/io.h> 36#include <asm/io.h>
39#include <asm/uaccess.h> 37#include <asm/uaccess.h>
@@ -368,6 +366,58 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr)
368} 366}
369 367
370/* 368/*
369 * This function is used to reevaluate whether the T-state is valid
370 * after one CPU is onlined/offlined.
371 * It is noted that it won't reevaluate the following properties for
372 * the T-state.
373 * 1. Control method.
374 * 2. the number of supported T-state
375 * 3. TSD domain
376 */
377void acpi_processor_reevaluate_tstate(struct acpi_processor *pr,
378 unsigned long action)
379{
380 int result = 0;
381
382 if (action == CPU_DEAD) {
383 /* When one CPU is offline, the T-state throttling
384 * will be invalidated.
385 */
386 pr->flags.throttling = 0;
387 return;
388 }
389 /* the following is to recheck whether the T-state is valid for
390 * the online CPU
391 */
392 if (!pr->throttling.state_count) {
393 /* If the number of T-state is invalid, it is
394 * invalidated.
395 */
396 pr->flags.throttling = 0;
397 return;
398 }
399 pr->flags.throttling = 1;
400
401 /* Disable throttling (if enabled). We'll let subsequent
402 * policy (e.g.thermal) decide to lower performance if it
403 * so chooses, but for now we'll crank up the speed.
404 */
405
406 result = acpi_processor_get_throttling(pr);
407 if (result)
408 goto end;
409
410 if (pr->throttling.state) {
411 result = acpi_processor_set_throttling(pr, 0, false);
412 if (result)
413 goto end;
414 }
415
416end:
417 if (result)
418 pr->flags.throttling = 0;
419}
420/*
371 * _PTC - Processor Throttling Control (and status) register location 421 * _PTC - Processor Throttling Control (and status) register location
372 */ 422 */
373static int acpi_processor_get_throttling_control(struct acpi_processor *pr) 423static int acpi_processor_get_throttling_control(struct acpi_processor *pr)
@@ -660,20 +710,14 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr)
660} 710}
661 711
662#ifdef CONFIG_X86 712#ifdef CONFIG_X86
663static int acpi_throttling_rdmsr(struct acpi_processor *pr, 713static int acpi_throttling_rdmsr(u64 *value)
664 u64 *value)
665{ 714{
666 struct cpuinfo_x86 *c;
667 u64 msr_high, msr_low; 715 u64 msr_high, msr_low;
668 unsigned int cpu;
669 u64 msr = 0; 716 u64 msr = 0;
670 int ret = -1; 717 int ret = -1;
671 718
672 cpu = pr->id; 719 if ((this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_INTEL) ||
673 c = &cpu_data(cpu); 720 !this_cpu_has(X86_FEATURE_ACPI)) {
674
675 if ((c->x86_vendor != X86_VENDOR_INTEL) ||
676 !cpu_has(c, X86_FEATURE_ACPI)) {
677 printk(KERN_ERR PREFIX 721 printk(KERN_ERR PREFIX
678 "HARDWARE addr space,NOT supported yet\n"); 722 "HARDWARE addr space,NOT supported yet\n");
679 } else { 723 } else {
@@ -688,18 +732,13 @@ static int acpi_throttling_rdmsr(struct acpi_processor *pr,
688 return ret; 732 return ret;
689} 733}
690 734
691static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value) 735static int acpi_throttling_wrmsr(u64 value)
692{ 736{
693 struct cpuinfo_x86 *c;
694 unsigned int cpu;
695 int ret = -1; 737 int ret = -1;
696 u64 msr; 738 u64 msr;
697 739
698 cpu = pr->id; 740 if ((this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_INTEL) ||
699 c = &cpu_data(cpu); 741 !this_cpu_has(X86_FEATURE_ACPI)) {
700
701 if ((c->x86_vendor != X86_VENDOR_INTEL) ||
702 !cpu_has(c, X86_FEATURE_ACPI)) {
703 printk(KERN_ERR PREFIX 742 printk(KERN_ERR PREFIX
704 "HARDWARE addr space,NOT supported yet\n"); 743 "HARDWARE addr space,NOT supported yet\n");
705 } else { 744 } else {
@@ -711,15 +750,14 @@ static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value)
711 return ret; 750 return ret;
712} 751}
713#else 752#else
714static int acpi_throttling_rdmsr(struct acpi_processor *pr, 753static int acpi_throttling_rdmsr(u64 *value)
715 u64 *value)
716{ 754{
717 printk(KERN_ERR PREFIX 755 printk(KERN_ERR PREFIX
718 "HARDWARE addr space,NOT supported yet\n"); 756 "HARDWARE addr space,NOT supported yet\n");
719 return -1; 757 return -1;
720} 758}
721 759
722static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value) 760static int acpi_throttling_wrmsr(u64 value)
723{ 761{
724 printk(KERN_ERR PREFIX 762 printk(KERN_ERR PREFIX
725 "HARDWARE addr space,NOT supported yet\n"); 763 "HARDWARE addr space,NOT supported yet\n");
@@ -751,7 +789,7 @@ static int acpi_read_throttling_status(struct acpi_processor *pr,
751 ret = 0; 789 ret = 0;
752 break; 790 break;
753 case ACPI_ADR_SPACE_FIXED_HARDWARE: 791 case ACPI_ADR_SPACE_FIXED_HARDWARE:
754 ret = acpi_throttling_rdmsr(pr, value); 792 ret = acpi_throttling_rdmsr(value);
755 break; 793 break;
756 default: 794 default:
757 printk(KERN_ERR PREFIX "Unknown addr space %d\n", 795 printk(KERN_ERR PREFIX "Unknown addr space %d\n",
@@ -784,7 +822,7 @@ static int acpi_write_throttling_state(struct acpi_processor *pr,
784 ret = 0; 822 ret = 0;
785 break; 823 break;
786 case ACPI_ADR_SPACE_FIXED_HARDWARE: 824 case ACPI_ADR_SPACE_FIXED_HARDWARE:
787 ret = acpi_throttling_wrmsr(pr, value); 825 ret = acpi_throttling_wrmsr(value);
788 break; 826 break;
789 default: 827 default:
790 printk(KERN_ERR PREFIX "Unknown addr space %d\n", 828 printk(KERN_ERR PREFIX "Unknown addr space %d\n",
@@ -874,7 +912,11 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
874 */ 912 */
875 cpumask_copy(saved_mask, &current->cpus_allowed); 913 cpumask_copy(saved_mask, &current->cpus_allowed);
876 /* FIXME: use work_on_cpu() */ 914 /* FIXME: use work_on_cpu() */
877 set_cpus_allowed_ptr(current, cpumask_of(pr->id)); 915 if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) {
916 /* Can't migrate to the target pr->id CPU. Exit */
917 free_cpumask_var(saved_mask);
918 return -ENODEV;
919 }
878 ret = pr->throttling.acpi_processor_get_throttling(pr); 920 ret = pr->throttling.acpi_processor_get_throttling(pr);
879 /* restore the previous state */ 921 /* restore the previous state */
880 set_cpus_allowed_ptr(current, saved_mask); 922 set_cpus_allowed_ptr(current, saved_mask);
@@ -1049,6 +1091,14 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
1049 return -ENOMEM; 1091 return -ENOMEM;
1050 } 1092 }
1051 1093
1094 if (cpu_is_offline(pr->id)) {
1095 /*
1096 * the cpu pointed by pr->id is offline. Unnecessary to change
1097 * the throttling state any more.
1098 */
1099 return -ENODEV;
1100 }
1101
1052 cpumask_copy(saved_mask, &current->cpus_allowed); 1102 cpumask_copy(saved_mask, &current->cpus_allowed);
1053 t_state.target_state = state; 1103 t_state.target_state = state;
1054 p_throttling = &(pr->throttling); 1104 p_throttling = &(pr->throttling);
@@ -1072,7 +1122,11 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
1072 */ 1122 */
1073 if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) { 1123 if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
1074 /* FIXME: use work_on_cpu() */ 1124 /* FIXME: use work_on_cpu() */
1075 set_cpus_allowed_ptr(current, cpumask_of(pr->id)); 1125 if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) {
1126 /* Can't migrate to the pr->id CPU. Exit */
1127 ret = -ENODEV;
1128 goto exit;
1129 }
1076 ret = p_throttling->acpi_processor_set_throttling(pr, 1130 ret = p_throttling->acpi_processor_set_throttling(pr,
1077 t_state.target_state, force); 1131 t_state.target_state, force);
1078 } else { 1132 } else {
@@ -1098,13 +1152,14 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
1098 */ 1152 */
1099 if (!match_pr->flags.throttling) { 1153 if (!match_pr->flags.throttling) {
1100 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 1154 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1101 "Throttling Controll is unsupported " 1155 "Throttling Control is unsupported "
1102 "on CPU %d\n", i)); 1156 "on CPU %d\n", i));
1103 continue; 1157 continue;
1104 } 1158 }
1105 t_state.cpu = i; 1159 t_state.cpu = i;
1106 /* FIXME: use work_on_cpu() */ 1160 /* FIXME: use work_on_cpu() */
1107 set_cpus_allowed_ptr(current, cpumask_of(i)); 1161 if (set_cpus_allowed_ptr(current, cpumask_of(i)))
1162 continue;
1108 ret = match_pr->throttling. 1163 ret = match_pr->throttling.
1109 acpi_processor_set_throttling( 1164 acpi_processor_set_throttling(
1110 match_pr, t_state.target_state, force); 1165 match_pr, t_state.target_state, force);
@@ -1124,6 +1179,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
1124 /* restore the previous state */ 1179 /* restore the previous state */
1125 /* FIXME: use work_on_cpu() */ 1180 /* FIXME: use work_on_cpu() */
1126 set_cpus_allowed_ptr(current, saved_mask); 1181 set_cpus_allowed_ptr(current, saved_mask);
1182exit:
1127 free_cpumask_var(online_throttling_cpus); 1183 free_cpumask_var(online_throttling_cpus);
1128 free_cpumask_var(saved_mask); 1184 free_cpumask_var(saved_mask);
1129 return ret; 1185 return ret;
@@ -1214,111 +1270,3 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
1214 return result; 1270 return result;
1215} 1271}
1216 1272
1217/* proc interface */
1218static int acpi_processor_throttling_seq_show(struct seq_file *seq,
1219 void *offset)
1220{
1221 struct acpi_processor *pr = seq->private;
1222 int i = 0;
1223 int result = 0;
1224
1225 if (!pr)
1226 goto end;
1227
1228 if (!(pr->throttling.state_count > 0)) {
1229 seq_puts(seq, "<not supported>\n");
1230 goto end;
1231 }
1232
1233 result = acpi_processor_get_throttling(pr);
1234
1235 if (result) {
1236 seq_puts(seq,
1237 "Could not determine current throttling state.\n");
1238 goto end;
1239 }
1240
1241 seq_printf(seq, "state count: %d\n"
1242 "active state: T%d\n"
1243 "state available: T%d to T%d\n",
1244 pr->throttling.state_count, pr->throttling.state,
1245 pr->throttling_platform_limit,
1246 pr->throttling.state_count - 1);
1247
1248 seq_puts(seq, "states:\n");
1249 if (pr->throttling.acpi_processor_get_throttling ==
1250 acpi_processor_get_throttling_fadt) {
1251 for (i = 0; i < pr->throttling.state_count; i++)
1252 seq_printf(seq, " %cT%d: %02d%%\n",
1253 (i == pr->throttling.state ? '*' : ' '), i,
1254 (pr->throttling.states[i].performance ? pr->
1255 throttling.states[i].performance / 10 : 0));
1256 } else {
1257 for (i = 0; i < pr->throttling.state_count; i++)
1258 seq_printf(seq, " %cT%d: %02d%%\n",
1259 (i == pr->throttling.state ? '*' : ' '), i,
1260 (int)pr->throttling.states_tss[i].
1261 freqpercentage);
1262 }
1263
1264 end:
1265 return 0;
1266}
1267
1268static int acpi_processor_throttling_open_fs(struct inode *inode,
1269 struct file *file)
1270{
1271 return single_open(file, acpi_processor_throttling_seq_show,
1272 PDE(inode)->data);
1273}
1274
1275static ssize_t acpi_processor_write_throttling(struct file *file,
1276 const char __user * buffer,
1277 size_t count, loff_t * data)
1278{
1279 int result = 0;
1280 struct seq_file *m = file->private_data;
1281 struct acpi_processor *pr = m->private;
1282 char state_string[5] = "";
1283 char *charp = NULL;
1284 size_t state_val = 0;
1285 char tmpbuf[5] = "";
1286
1287 if (!pr || (count > sizeof(state_string) - 1))
1288 return -EINVAL;
1289
1290 if (copy_from_user(state_string, buffer, count))
1291 return -EFAULT;
1292
1293 state_string[count] = '\0';
1294 if ((count > 0) && (state_string[count-1] == '\n'))
1295 state_string[count-1] = '\0';
1296
1297 charp = state_string;
1298 if ((state_string[0] == 't') || (state_string[0] == 'T'))
1299 charp++;
1300
1301 state_val = simple_strtoul(charp, NULL, 0);
1302 if (state_val >= pr->throttling.state_count)
1303 return -EINVAL;
1304
1305 snprintf(tmpbuf, 5, "%zu", state_val);
1306
1307 if (strcmp(tmpbuf, charp) != 0)
1308 return -EINVAL;
1309
1310 result = acpi_processor_set_throttling(pr, state_val, false);
1311 if (result)
1312 return result;
1313
1314 return count;
1315}
1316
1317const struct file_operations acpi_processor_throttling_fops = {
1318 .owner = THIS_MODULE,
1319 .open = acpi_processor_throttling_open_fs,
1320 .read = seq_read,
1321 .write = acpi_processor_write_throttling,
1322 .llseek = seq_lseek,
1323 .release = single_release,
1324};