1 // SPDX-License-Identifier: GPL-2.0 2 #include <unistd.h> 3 #include <stdio.h> 4 #include <errno.h> 5 #include <stdlib.h> 6 #include <limits.h> 7 #include <string.h> 8 #include <ctype.h> 9 #include <getopt.h> 10 11 #include <cpufreq.h> 12 #include <cpuidle.h> 13 14 #include "helpers/helpers.h" 15 16 static struct option info_opts[] = { 17 {"disable", required_argument, NULL, 'd'}, 18 {"enable", required_argument, NULL, 'e'}, 19 {"disable-by-latency", required_argument, NULL, 'D'}, 20 {"enable-all", no_argument, NULL, 'E'}, 21 { }, 22 }; 23 24 25 int cmd_idle_set(int argc, char **argv) 26 { 27 extern char *optarg; 28 extern int optind, opterr, optopt; 29 int ret = 0, cont = 1, param = 0, disabled; 30 unsigned long long latency = 0, state_latency; 31 unsigned int cpu = 0, idlestate = 0, idlestates = 0; 32 char *endptr; 33 34 do { 35 ret = getopt_long(argc, argv, "d:e:ED:", info_opts, NULL); 36 if (ret == -1) 37 break; 38 switch (ret) { 39 case '?': 40 param = '?'; 41 cont = 0; 42 break; 43 case 'd': 44 case 'e': 45 if (param) { 46 param = -1; 47 cont = 0; 48 break; 49 } 50 param = ret; 51 strtol(optarg, &endptr, 10); 52 if (*endptr != '\0') { 53 printf(_("Bad value: %s, Integer expected\n"), optarg); 54 exit(EXIT_FAILURE); 55 } else { 56 idlestate = atoi(optarg); 57 } 58 break; 59 case 'D': 60 if (param) { 61 param = -1; 62 cont = 0; 63 break; 64 } 65 param = ret; 66 latency = strtoull(optarg, &endptr, 10); 67 if (*endptr != '\0') { 68 printf(_("Bad latency value: %s\n"), optarg); 69 exit(EXIT_FAILURE); 70 } 71 break; 72 case 'E': 73 if (param) { 74 param = -1; 75 cont = 0; 76 break; 77 } 78 param = ret; 79 break; 80 case -1: 81 cont = 0; 82 break; 83 } 84 } while (cont); 85 86 switch (param) { 87 case -1: 88 printf(_("You can't specify more than one " 89 "output-specific argument\n")); 90 exit(EXIT_FAILURE); 91 case '?': 92 printf(_("invalid or unknown argument\n")); 93 exit(EXIT_FAILURE); 94 } 95 96 get_cpustate(); 97 98 /* Default is: set all CPUs */ 99 if (bitmask_isallclear(cpus_chosen)) 100 bitmask_setall(cpus_chosen); 101 102 for (cpu = bitmask_first(cpus_chosen); 103 cpu <= bitmask_last(cpus_chosen); cpu++) { 104 105 if (!bitmask_isbitset(cpus_chosen, cpu)) 106 continue; 107 108 if (cpupower_is_cpu_online(cpu) != 1) 109 continue; 110 111 idlestates = cpuidle_state_count(cpu); 112 if (idlestates <= 0) 113 continue; 114 115 switch (param) { 116 case 'd': 117 ret = cpuidle_state_disable(cpu, idlestate, 1); 118 if (ret == 0) 119 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu); 120 else if (ret == -1) 121 printf(_("Idlestate %u not available on CPU %u\n"), 122 idlestate, cpu); 123 else if (ret == -2) 124 printf(_("Idlestate disabling not supported by kernel\n")); 125 else 126 printf(_("Idlestate %u not disabled on CPU %u\n"), 127 idlestate, cpu); 128 break; 129 case 'e': 130 ret = cpuidle_state_disable(cpu, idlestate, 0); 131 if (ret == 0) 132 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 133 else if (ret == -1) 134 printf(_("Idlestate %u not available on CPU %u\n"), 135 idlestate, cpu); 136 else if (ret == -2) 137 printf(_("Idlestate enabling not supported by kernel\n")); 138 else 139 printf(_("Idlestate %u not enabled on CPU %u\n"), 140 idlestate, cpu); 141 break; 142 case 'D': 143 for (idlestate = 0; idlestate < idlestates; idlestate++) { 144 disabled = cpuidle_is_state_disabled 145 (cpu, idlestate); 146 state_latency = cpuidle_state_latency 147 (cpu, idlestate); 148 if (disabled == 1) { 149 if (latency > state_latency){ 150 ret = cpuidle_state_disable 151 (cpu, idlestate, 0); 152 if (ret == 0) 153 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 154 } 155 continue; 156 } 157 if (latency <= state_latency){ 158 ret = cpuidle_state_disable 159 (cpu, idlestate, 1); 160 if (ret == 0) 161 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu); 162 } 163 } 164 break; 165 case 'E': 166 for (idlestate = 0; idlestate < idlestates; idlestate++) { 167 disabled = cpuidle_is_state_disabled 168 (cpu, idlestate); 169 if (disabled == 1) { 170 ret = cpuidle_state_disable 171 (cpu, idlestate, 0); 172 if (ret == 0) 173 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 174 } 175 } 176 break; 177 default: 178 /* Not reachable with proper args checking */ 179 printf(_("Invalid or unknown argument\n")); 180 exit(EXIT_FAILURE); 181 break; 182 } 183 } 184 185 print_offline_cpus(); 186 return EXIT_SUCCESS; 187 } 188