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 static struct option set_opts[] = { 21 { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'}, 22 { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'}, 23 { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'}, 24 { }, 25 }; 26 27 static void print_wrong_arg_exit(void) 28 { 29 printf(_("invalid or unknown argument\n")); 30 exit(EXIT_FAILURE); 31 } 32 33 int cmd_set(int argc, char **argv) 34 { 35 extern char *optarg; 36 extern int optind, opterr, optopt; 37 unsigned int cpu; 38 39 union { 40 struct { 41 int sched_mc:1; 42 int sched_smt:1; 43 int perf_bias:1; 44 }; 45 int params; 46 } params; 47 int sched_mc = 0, sched_smt = 0, perf_bias = 0; 48 int ret = 0; 49 50 setlocale(LC_ALL, ""); 51 textdomain(PACKAGE); 52 53 params.params = 0; 54 /* parameter parsing */ 55 while ((ret = getopt_long(argc, argv, "m:s:b:", 56 set_opts, NULL)) != -1) { 57 switch (ret) { 58 case 'b': 59 if (params.perf_bias) 60 print_wrong_arg_exit(); 61 perf_bias = atoi(optarg); 62 if (perf_bias < 0 || perf_bias > 15) { 63 printf(_("--perf-bias param out " 64 "of range [0-%d]\n"), 15); 65 print_wrong_arg_exit(); 66 } 67 params.perf_bias = 1; 68 break; 69 case 'm': 70 if (params.sched_mc) 71 print_wrong_arg_exit(); 72 sched_mc = atoi(optarg); 73 if (sched_mc < 0 || sched_mc > 2) { 74 printf(_("--sched-mc param out " 75 "of range [0-%d]\n"), 2); 76 print_wrong_arg_exit(); 77 } 78 params.sched_mc = 1; 79 break; 80 case 's': 81 if (params.sched_smt) 82 print_wrong_arg_exit(); 83 sched_smt = atoi(optarg); 84 if (sched_smt < 0 || sched_smt > 2) { 85 printf(_("--sched-smt param out " 86 "of range [0-%d]\n"), 2); 87 print_wrong_arg_exit(); 88 } 89 params.sched_smt = 1; 90 break; 91 default: 92 print_wrong_arg_exit(); 93 } 94 }; 95 96 if (!params.params) 97 print_wrong_arg_exit(); 98 99 if (params.sched_mc) { 100 ret = sysfs_set_sched("mc", sched_mc); 101 if (ret) 102 fprintf(stderr, _("Error setting sched-mc %s\n"), 103 (ret == -ENODEV) ? "not supported" : ""); 104 } 105 if (params.sched_smt) { 106 ret = sysfs_set_sched("smt", sched_smt); 107 if (ret) 108 fprintf(stderr, _("Error setting sched-smt %s\n"), 109 (ret == -ENODEV) ? "not supported" : ""); 110 } 111 112 /* Default is: set all CPUs */ 113 if (bitmask_isallclear(cpus_chosen)) 114 bitmask_setall(cpus_chosen); 115 116 /* loop over CPUs */ 117 for (cpu = bitmask_first(cpus_chosen); 118 cpu <= bitmask_last(cpus_chosen); cpu++) { 119 120 if (!bitmask_isbitset(cpus_chosen, cpu) || 121 cpufreq_cpu_exists(cpu)) 122 continue; 123 124 if (params.perf_bias) { 125 ret = msr_intel_set_perf_bias(cpu, perf_bias); 126 if (ret) { 127 fprintf(stderr, _("Error setting perf-bias " 128 "value on CPU %d\n"), cpu); 129 break; 130 } 131 } 132 } 133 return ret; 134 } 135