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