blob: 569f268f4c7ffe53a86014f2ccb6c02a957cc946 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Thomas Renningerc4f3610e2013-06-28 15:34:31 +02002#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>
Thomas Renningerc4f3610e2013-06-28 15:34:31 +02009#include <getopt.h>
10
Thomas Renningerac5a1812016-04-28 15:24:40 +020011#include <cpufreq.h>
12#include <cpuidle.h>
13
Thomas Renningerc4f3610e2013-06-28 15:34:31 +020014#include "helpers/helpers.h"
Thomas Renningerc4f3610e2013-06-28 15:34:31 +020015
16static struct option info_opts[] = {
Sriram Raghunathan57ab3b082015-10-23 09:52:45 +020017 {"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 { },
Thomas Renningerc4f3610e2013-06-28 15:34:31 +020022};
23
24
25int cmd_idle_set(int argc, char **argv)
26{
27 extern char *optarg;
28 extern int optind, opterr, optopt;
Thomas Renninger69cd5022014-05-13 12:41:41 +020029 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;
Thomas Renningerc4f3610e2013-06-28 15:34:31 +020033
34 do {
Thomas Renninger69cd5022014-05-13 12:41:41 +020035 ret = getopt_long(argc, argv, "d:e:ED:", info_opts, NULL);
Thomas Renningerc4f3610e2013-06-28 15:34:31 +020036 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;
Thomas Renninger69cd5022014-05-13 12:41:41 +020061 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;
Thomas Renningerc4f3610e2013-06-28 15:34:31 +020082 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 /* 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
Thomas Renningerac5a1812016-04-28 15:24:40 +0200108 if (cpupower_is_cpu_online(cpu) != 1)
Thomas Renninger69cd5022014-05-13 12:41:41 +0200109 continue;
Thomas Renningerc4f3610e2013-06-28 15:34:31 +0200110
Thomas Renningerac5a1812016-04-28 15:24:40 +0200111 idlestates = cpuidle_state_count(cpu);
Thomas Renninger69cd5022014-05-13 12:41:41 +0200112 if (idlestates <= 0)
113 continue;
114
115 switch (param) {
Thomas Renningerc4f3610e2013-06-28 15:34:31 +0200116 case 'd':
Thomas Renningerac5a1812016-04-28 15:24:40 +0200117 ret = cpuidle_state_disable(cpu, idlestate, 1);
Thomas Renningerc4f3610e2013-06-28 15:34:31 +0200118 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':
Thomas Renningerac5a1812016-04-28 15:24:40 +0200130 ret = cpuidle_state_disable(cpu, idlestate, 0);
Thomas Renningerc4f3610e2013-06-28 15:34:31 +0200131 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;
Thomas Renninger69cd5022014-05-13 12:41:41 +0200142 case 'D':
143 for (idlestate = 0; idlestate < idlestates; idlestate++) {
Thomas Renningerac5a1812016-04-28 15:24:40 +0200144 disabled = cpuidle_is_state_disabled
Thomas Renninger69cd5022014-05-13 12:41:41 +0200145 (cpu, idlestate);
Thomas Renningerac5a1812016-04-28 15:24:40 +0200146 state_latency = cpuidle_state_latency
Thomas Renninger69cd5022014-05-13 12:41:41 +0200147 (cpu, idlestate);
Thomas Renninger19c9fb82015-10-22 17:17:07 +0200148 if (disabled == 1) {
149 if (latency > state_latency){
Thomas Renningerac5a1812016-04-28 15:24:40 +0200150 ret = cpuidle_state_disable
Thomas Renninger19c9fb82015-10-22 17:17:07 +0200151 (cpu, idlestate, 0);
152 if (ret == 0)
153 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
154 }
Thomas Renninger69cd5022014-05-13 12:41:41 +0200155 continue;
Thomas Renninger19c9fb82015-10-22 17:17:07 +0200156 }
157 if (latency <= state_latency){
Thomas Renningerac5a1812016-04-28 15:24:40 +0200158 ret = cpuidle_state_disable
Thomas Renninger19c9fb82015-10-22 17:17:07 +0200159 (cpu, idlestate, 1);
160 if (ret == 0)
Thomas Renninger69cd5022014-05-13 12:41:41 +0200161 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu);
Thomas Renninger19c9fb82015-10-22 17:17:07 +0200162 }
Thomas Renninger69cd5022014-05-13 12:41:41 +0200163 }
164 break;
165 case 'E':
166 for (idlestate = 0; idlestate < idlestates; idlestate++) {
Thomas Renningerac5a1812016-04-28 15:24:40 +0200167 disabled = cpuidle_is_state_disabled
Thomas Renninger69cd5022014-05-13 12:41:41 +0200168 (cpu, idlestate);
169 if (disabled == 1) {
Thomas Renningerac5a1812016-04-28 15:24:40 +0200170 ret = cpuidle_state_disable
Thomas Renninger69cd5022014-05-13 12:41:41 +0200171 (cpu, idlestate, 0);
172 if (ret == 0)
173 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
174 }
175 }
176 break;
Thomas Renningerc4f3610e2013-06-28 15:34:31 +0200177 default:
178 /* Not reachable with proper args checking */
179 printf(_("Invalid or unknown argument\n"));
180 exit(EXIT_FAILURE);
181 break;
182 }
183 }
184 return EXIT_SUCCESS;
185}