1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc. 4 */ 5 6 7 #include <unistd.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <errno.h> 11 #include <string.h> 12 #include <getopt.h> 13 #include <sys/utsname.h> 14 15 #include "helpers/helpers.h" 16 #include "helpers/sysfs.h" 17 #include "helpers/bitmask.h" 18 19 static struct option set_opts[] = { 20 {"perf-bias", required_argument, NULL, 'b'}, 21 {"epp", required_argument, NULL, 'e'}, 22 {"amd-pstate-mode", required_argument, NULL, 'm'}, 23 { }, 24 }; 25 26 static void print_wrong_arg_exit(void) 27 { 28 printf(_("invalid or unknown argument\n")); 29 exit(EXIT_FAILURE); 30 } 31 32 int cmd_set(int argc, char **argv) 33 { 34 extern char *optarg; 35 extern int optind, opterr, optopt; 36 unsigned int cpu; 37 struct utsname uts; 38 39 union { 40 struct { 41 int perf_bias:1; 42 int epp:1; 43 int mode:1; 44 }; 45 int params; 46 } params; 47 int perf_bias = 0; 48 int ret = 0; 49 char epp[30], mode[20]; 50 51 ret = uname(&uts); 52 if (!ret && (!strcmp(uts.machine, "ppc64le") || 53 !strcmp(uts.machine, "ppc64"))) { 54 fprintf(stderr, _("Subcommand not supported on POWER.\n")); 55 return ret; 56 } 57 58 setlocale(LC_ALL, ""); 59 textdomain(PACKAGE); 60 61 params.params = 0; 62 /* parameter parsing */ 63 while ((ret = getopt_long(argc, argv, "b:e:m:", 64 set_opts, NULL)) != -1) { 65 switch (ret) { 66 case 'b': 67 if (params.perf_bias) 68 print_wrong_arg_exit(); 69 perf_bias = atoi(optarg); 70 if (perf_bias < 0 || perf_bias > 15) { 71 printf(_("--perf-bias param out " 72 "of range [0-%d]\n"), 15); 73 print_wrong_arg_exit(); 74 } 75 params.perf_bias = 1; 76 break; 77 case 'e': 78 if (params.epp) 79 print_wrong_arg_exit(); 80 if (sscanf(optarg, "%29s", epp) != 1) { 81 print_wrong_arg_exit(); 82 return -EINVAL; 83 } 84 params.epp = 1; 85 break; 86 case 'm': 87 if (cpupower_cpu_info.vendor != X86_VENDOR_AMD) 88 print_wrong_arg_exit(); 89 if (params.mode) 90 print_wrong_arg_exit(); 91 if (sscanf(optarg, "%19s", mode) != 1) { 92 print_wrong_arg_exit(); 93 return -EINVAL; 94 } 95 params.mode = 1; 96 break; 97 default: 98 print_wrong_arg_exit(); 99 } 100 } 101 102 if (!params.params) 103 print_wrong_arg_exit(); 104 105 if (params.mode) { 106 ret = cpupower_set_amd_pstate_mode(mode); 107 if (ret) 108 fprintf(stderr, "Error setting mode\n"); 109 } 110 111 /* Default is: set all CPUs */ 112 if (bitmask_isallclear(cpus_chosen)) 113 bitmask_setall(cpus_chosen); 114 115 /* loop over CPUs */ 116 for (cpu = bitmask_first(cpus_chosen); 117 cpu <= bitmask_last(cpus_chosen); cpu++) { 118 119 if (!bitmask_isbitset(cpus_chosen, cpu)) 120 continue; 121 122 if (sysfs_is_cpu_online(cpu) != 1){ 123 fprintf(stderr, _("Cannot set values on CPU %d:"), cpu); 124 fprintf(stderr, _(" *is offline\n")); 125 continue; 126 } 127 128 if (params.perf_bias) { 129 ret = cpupower_intel_set_perf_bias(cpu, perf_bias); 130 if (ret) { 131 fprintf(stderr, _("Error setting perf-bias " 132 "value on CPU %d\n"), cpu); 133 break; 134 } 135 } 136 137 if (params.epp) { 138 ret = cpupower_set_epp(cpu, epp); 139 if (ret) { 140 fprintf(stderr, 141 "Error setting epp value on CPU %d\n", cpu); 142 break; 143 } 144 } 145 146 } 147 return ret; 148 } 149