1 /* 2 * (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc. 3 * 4 * Licensed under the terms of the GNU GPL License version 2. 5 */ 6 7 8 #include <unistd.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <errno.h> 12 #include <string.h> 13 #include <getopt.h> 14 15 #include <cpufreq.h> 16 #include "helpers/helpers.h" 17 #include "helpers/sysfs.h" 18 #include "helpers/bitmask.h" 19 20 void set_help(void) 21 { 22 printf(_("Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n")); 23 printf(_("Options:\n")); 24 printf(_(" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n" 25 " Intel models [0-15], see manpage for details\n")); 26 printf(_(" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n")); 27 printf(_(" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler policy.\n")); 28 printf(_(" -h, --help Prints out this screen\n")); 29 printf("\n"); 30 } 31 32 static struct option set_opts[] = { 33 { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'}, 34 { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'}, 35 { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'}, 36 { .name = "help", .has_arg = no_argument, .flag = NULL, .val = 'h'}, 37 { }, 38 }; 39 40 static void print_wrong_arg_exit(void) 41 { 42 printf(_("invalid or unknown argument\n")); 43 set_help(); 44 exit(EXIT_FAILURE); 45 } 46 47 int cmd_set(int argc, char **argv) 48 { 49 extern char *optarg; 50 extern int optind, opterr, optopt; 51 unsigned int cpu; 52 53 union { 54 struct { 55 int sched_mc:1; 56 int sched_smt:1; 57 int perf_bias:1; 58 }; 59 int params; 60 } params; 61 int sched_mc = 0, sched_smt = 0, perf_bias = 0; 62 int ret = 0; 63 64 setlocale(LC_ALL, ""); 65 textdomain(PACKAGE); 66 67 params.params = 0; 68 /* parameter parsing */ 69 while ((ret = getopt_long(argc, argv, "m:s:b:h", 70 set_opts, NULL)) != -1) { 71 switch (ret) { 72 case 'h': 73 set_help(); 74 return 0; 75 case 'b': 76 if (params.perf_bias) 77 print_wrong_arg_exit(); 78 perf_bias = atoi(optarg); 79 if (perf_bias < 0 || perf_bias > 15) { 80 printf(_("--perf-bias param out " 81 "of range [0-%d]\n"), 15); 82 print_wrong_arg_exit(); 83 } 84 params.perf_bias = 1; 85 break; 86 case 'm': 87 if (params.sched_mc) 88 print_wrong_arg_exit(); 89 sched_mc = atoi(optarg); 90 if (sched_mc < 0 || sched_mc > 2) { 91 printf(_("--sched-mc param out " 92 "of range [0-%d]\n"), 2); 93 print_wrong_arg_exit(); 94 } 95 params.sched_mc = 1; 96 break; 97 case 's': 98 if (params.sched_smt) 99 print_wrong_arg_exit(); 100 sched_smt = atoi(optarg); 101 if (sched_smt < 0 || sched_smt > 2) { 102 printf(_("--sched-smt param out " 103 "of range [0-%d]\n"), 2); 104 print_wrong_arg_exit(); 105 } 106 params.sched_smt = 1; 107 break; 108 default: 109 print_wrong_arg_exit(); 110 } 111 }; 112 113 if (!params.params) { 114 set_help(); 115 return -EINVAL; 116 } 117 118 if (params.sched_mc) { 119 ret = sysfs_set_sched("mc", sched_mc); 120 if (ret) 121 fprintf(stderr, _("Error setting sched-mc %s\n"), 122 (ret == -ENODEV) ? "not supported" : ""); 123 } 124 if (params.sched_smt) { 125 ret = sysfs_set_sched("smt", sched_smt); 126 if (ret) 127 fprintf(stderr, _("Error setting sched-smt %s\n"), 128 (ret == -ENODEV) ? "not supported" : ""); 129 } 130 131 /* Default is: set all CPUs */ 132 if (bitmask_isallclear(cpus_chosen)) 133 bitmask_setall(cpus_chosen); 134 135 /* loop over CPUs */ 136 for (cpu = bitmask_first(cpus_chosen); 137 cpu <= bitmask_last(cpus_chosen); cpu++) { 138 139 if (!bitmask_isbitset(cpus_chosen, cpu) || 140 cpufreq_cpu_exists(cpu)) 141 continue; 142 143 if (params.perf_bias) { 144 ret = msr_intel_set_perf_bias(cpu, perf_bias); 145 if (ret) { 146 fprintf(stderr, _("Error setting perf-bias " 147 "value on CPU %d\n"), cpu); 148 break; 149 } 150 } 151 } 152 return ret; 153 } 154