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 if (param) { 45 param = -1; 46 cont = 0; 47 break; 48 } 49 param = ret; 50 idlestate = atoi(optarg); 51 break; 52 case 'e': 53 if (param) { 54 param = -1; 55 cont = 0; 56 break; 57 } 58 param = ret; 59 idlestate = atoi(optarg); 60 break; 61 case 'D': 62 if (param) { 63 param = -1; 64 cont = 0; 65 break; 66 } 67 param = ret; 68 latency = strtoull(optarg, &endptr, 10); 69 if (*endptr != '\0') { 70 printf(_("Bad latency value: %s\n"), optarg); 71 exit(EXIT_FAILURE); 72 } 73 break; 74 case 'E': 75 if (param) { 76 param = -1; 77 cont = 0; 78 break; 79 } 80 param = ret; 81 break; 82 case -1: 83 cont = 0; 84 break; 85 } 86 } while (cont); 87 88 switch (param) { 89 case -1: 90 printf(_("You can't specify more than one " 91 "output-specific argument\n")); 92 exit(EXIT_FAILURE); 93 case '?': 94 printf(_("invalid or unknown argument\n")); 95 exit(EXIT_FAILURE); 96 } 97 98 get_cpustate(); 99 100 /* Default is: set all CPUs */ 101 if (bitmask_isallclear(cpus_chosen)) 102 bitmask_setall(cpus_chosen); 103 104 for (cpu = bitmask_first(cpus_chosen); 105 cpu <= bitmask_last(cpus_chosen); cpu++) { 106 107 if (!bitmask_isbitset(cpus_chosen, cpu)) 108 continue; 109 110 if (cpupower_is_cpu_online(cpu) != 1) 111 continue; 112 113 idlestates = cpuidle_state_count(cpu); 114 if (idlestates <= 0) 115 continue; 116 117 switch (param) { 118 case 'd': 119 ret = cpuidle_state_disable(cpu, idlestate, 1); 120 if (ret == 0) 121 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu); 122 else if (ret == -1) 123 printf(_("Idlestate %u not available on CPU %u\n"), 124 idlestate, cpu); 125 else if (ret == -2) 126 printf(_("Idlestate disabling not supported by kernel\n")); 127 else 128 printf(_("Idlestate %u not disabled on CPU %u\n"), 129 idlestate, cpu); 130 break; 131 case 'e': 132 ret = cpuidle_state_disable(cpu, idlestate, 0); 133 if (ret == 0) 134 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 135 else if (ret == -1) 136 printf(_("Idlestate %u not available on CPU %u\n"), 137 idlestate, cpu); 138 else if (ret == -2) 139 printf(_("Idlestate enabling not supported by kernel\n")); 140 else 141 printf(_("Idlestate %u not enabled on CPU %u\n"), 142 idlestate, cpu); 143 break; 144 case 'D': 145 for (idlestate = 0; idlestate < idlestates; idlestate++) { 146 disabled = cpuidle_is_state_disabled 147 (cpu, idlestate); 148 state_latency = cpuidle_state_latency 149 (cpu, idlestate); 150 if (disabled == 1) { 151 if (latency > state_latency){ 152 ret = cpuidle_state_disable 153 (cpu, idlestate, 0); 154 if (ret == 0) 155 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 156 } 157 continue; 158 } 159 if (latency <= state_latency){ 160 ret = cpuidle_state_disable 161 (cpu, idlestate, 1); 162 if (ret == 0) 163 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu); 164 } 165 } 166 break; 167 case 'E': 168 for (idlestate = 0; idlestate < idlestates; idlestate++) { 169 disabled = cpuidle_is_state_disabled 170 (cpu, idlestate); 171 if (disabled == 1) { 172 ret = cpuidle_state_disable 173 (cpu, idlestate, 0); 174 if (ret == 0) 175 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 176 } 177 } 178 break; 179 default: 180 /* Not reachable with proper args checking */ 181 printf(_("Invalid or unknown argument\n")); 182 exit(EXIT_FAILURE); 183 break; 184 } 185 } 186 187 print_offline_cpus(); 188 return EXIT_SUCCESS; 189 } 190