| Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 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 |  | 
| Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 20 | static struct option set_opts[] = { | 
| Dominik Brodowski | a1ce5ba | 2011-04-19 20:33:50 +0200 | [diff] [blame] | 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'}, | 
| Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 24 | { }, | 
|  | 25 | }; | 
|  | 26 |  | 
|  | 27 | static void print_wrong_arg_exit(void) | 
|  | 28 | { | 
|  | 29 | printf(_("invalid or unknown argument\n")); | 
| Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 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; | 
| Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 46 | } params; | 
|  | 47 | int sched_mc = 0, sched_smt = 0, perf_bias = 0; | 
|  | 48 | int ret = 0; | 
|  | 49 |  | 
|  | 50 | setlocale(LC_ALL, ""); | 
| Dominik Brodowski | a1ce5ba | 2011-04-19 20:33:50 +0200 | [diff] [blame] | 51 | textdomain(PACKAGE); | 
| Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 52 |  | 
|  | 53 | params.params = 0; | 
|  | 54 | /* parameter parsing */ | 
| Dominik Brodowski | 498ca79 | 2011-08-06 18:11:43 +0200 | [diff] [blame] | 55 | while ((ret = getopt_long(argc, argv, "m:s:b:", | 
| Dominik Brodowski | a1ce5ba | 2011-04-19 20:33:50 +0200 | [diff] [blame] | 56 | set_opts, NULL)) != -1) { | 
| Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 57 | switch (ret) { | 
| Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 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 |  | 
| Dominik Brodowski | 498ca79 | 2011-08-06 18:11:43 +0200 | [diff] [blame] | 96 | if (!params.params) | 
|  | 97 | print_wrong_arg_exit(); | 
| Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 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++) { | 
| Dominik Brodowski | a1ce5ba | 2011-04-19 20:33:50 +0200 | [diff] [blame] | 119 |  | 
| Dominik Brodowski | 7fe2f63 | 2011-03-30 16:30:11 +0200 | [diff] [blame] | 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 | } |