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