xref: /OK3568_Linux_fs/kernel/tools/power/x86/intel-speed-select/isst-config.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Intel Speed Select -- Enumerate and control features
4*4882a593Smuzhiyun  * Copyright (c) 2019 Intel Corporation.
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <linux/isst_if.h>
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include "isst.h"
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun struct process_cmd_struct {
12*4882a593Smuzhiyun 	char *feature;
13*4882a593Smuzhiyun 	char *command;
14*4882a593Smuzhiyun 	void (*process_fn)(int arg);
15*4882a593Smuzhiyun 	int arg;
16*4882a593Smuzhiyun };
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun static const char *version_str = "v1.6";
19*4882a593Smuzhiyun static const int supported_api_ver = 1;
20*4882a593Smuzhiyun static struct isst_if_platform_info isst_platform_info;
21*4882a593Smuzhiyun static char *progname;
22*4882a593Smuzhiyun static int debug_flag;
23*4882a593Smuzhiyun static FILE *outf;
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun static int cpu_model;
26*4882a593Smuzhiyun static int cpu_stepping;
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define MAX_CPUS_IN_ONE_REQ 256
29*4882a593Smuzhiyun static short max_target_cpus;
30*4882a593Smuzhiyun static unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ];
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun static int topo_max_cpus;
33*4882a593Smuzhiyun static size_t present_cpumask_size;
34*4882a593Smuzhiyun static cpu_set_t *present_cpumask;
35*4882a593Smuzhiyun static size_t target_cpumask_size;
36*4882a593Smuzhiyun static cpu_set_t *target_cpumask;
37*4882a593Smuzhiyun static int tdp_level = 0xFF;
38*4882a593Smuzhiyun static int fact_bucket = 0xFF;
39*4882a593Smuzhiyun static int fact_avx = 0xFF;
40*4882a593Smuzhiyun static unsigned long long fact_trl;
41*4882a593Smuzhiyun static int out_format_json;
42*4882a593Smuzhiyun static int cmd_help;
43*4882a593Smuzhiyun static int force_online_offline;
44*4882a593Smuzhiyun static int auto_mode;
45*4882a593Smuzhiyun static int fact_enable_fail;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun static int mbox_delay;
48*4882a593Smuzhiyun static int mbox_retries = 3;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun /* clos related */
51*4882a593Smuzhiyun static int current_clos = -1;
52*4882a593Smuzhiyun static int clos_epp = -1;
53*4882a593Smuzhiyun static int clos_prop_prio = -1;
54*4882a593Smuzhiyun static int clos_min = -1;
55*4882a593Smuzhiyun static int clos_max = -1;
56*4882a593Smuzhiyun static int clos_desired = -1;
57*4882a593Smuzhiyun static int clos_priority_type;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun struct _cpu_map {
60*4882a593Smuzhiyun 	unsigned short core_id;
61*4882a593Smuzhiyun 	unsigned short pkg_id;
62*4882a593Smuzhiyun 	unsigned short die_id;
63*4882a593Smuzhiyun 	unsigned short punit_cpu;
64*4882a593Smuzhiyun 	unsigned short punit_cpu_core;
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun struct _cpu_map *cpu_map;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun struct cpu_topology {
69*4882a593Smuzhiyun 	short cpu;
70*4882a593Smuzhiyun 	short core_id;
71*4882a593Smuzhiyun 	short pkg_id;
72*4882a593Smuzhiyun 	short die_id;
73*4882a593Smuzhiyun };
74*4882a593Smuzhiyun 
get_output_file(void)75*4882a593Smuzhiyun FILE *get_output_file(void)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun 	return outf;
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun 
debug_printf(const char * format,...)80*4882a593Smuzhiyun void debug_printf(const char *format, ...)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun 	va_list args;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	va_start(args, format);
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	if (debug_flag)
87*4882a593Smuzhiyun 		vprintf(format, args);
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	va_end(args);
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 
is_clx_n_platform(void)93*4882a593Smuzhiyun int is_clx_n_platform(void)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun 	if (cpu_model == 0x55)
96*4882a593Smuzhiyun 		if (cpu_stepping == 0x6 || cpu_stepping == 0x7)
97*4882a593Smuzhiyun 			return 1;
98*4882a593Smuzhiyun 	return 0;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun 
is_skx_based_platform(void)101*4882a593Smuzhiyun int is_skx_based_platform(void)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	if (cpu_model == 0x55)
104*4882a593Smuzhiyun 		return 1;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	return 0;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
update_cpu_model(void)109*4882a593Smuzhiyun static int update_cpu_model(void)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	unsigned int ebx, ecx, edx;
112*4882a593Smuzhiyun 	unsigned int fms, family;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	__cpuid(1, fms, ebx, ecx, edx);
115*4882a593Smuzhiyun 	family = (fms >> 8) & 0xf;
116*4882a593Smuzhiyun 	cpu_model = (fms >> 4) & 0xf;
117*4882a593Smuzhiyun 	if (family == 6 || family == 0xf)
118*4882a593Smuzhiyun 		cpu_model += ((fms >> 16) & 0xf) << 4;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	cpu_stepping = fms & 0xf;
121*4882a593Smuzhiyun 	/* only three CascadeLake-N models are supported */
122*4882a593Smuzhiyun 	if (is_clx_n_platform()) {
123*4882a593Smuzhiyun 		FILE *fp;
124*4882a593Smuzhiyun 		size_t n = 0;
125*4882a593Smuzhiyun 		char *line = NULL;
126*4882a593Smuzhiyun 		int ret = 1;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 		fp = fopen("/proc/cpuinfo", "r");
129*4882a593Smuzhiyun 		if (!fp)
130*4882a593Smuzhiyun 			err(-1, "cannot open /proc/cpuinfo\n");
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 		while (getline(&line, &n, fp) > 0) {
133*4882a593Smuzhiyun 			if (strstr(line, "model name")) {
134*4882a593Smuzhiyun 				if (strstr(line, "6252N") ||
135*4882a593Smuzhiyun 				    strstr(line, "6230N") ||
136*4882a593Smuzhiyun 				    strstr(line, "5218N"))
137*4882a593Smuzhiyun 					ret = 0;
138*4882a593Smuzhiyun 				break;
139*4882a593Smuzhiyun 			}
140*4882a593Smuzhiyun 		}
141*4882a593Smuzhiyun 		free(line);
142*4882a593Smuzhiyun 		fclose(fp);
143*4882a593Smuzhiyun 		return ret;
144*4882a593Smuzhiyun 	}
145*4882a593Smuzhiyun 	return 0;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun /* Open a file, and exit on failure */
fopen_or_exit(const char * path,const char * mode)149*4882a593Smuzhiyun static FILE *fopen_or_exit(const char *path, const char *mode)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun 	FILE *filep = fopen(path, mode);
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	if (!filep)
154*4882a593Smuzhiyun 		err(1, "%s: open failed", path);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	return filep;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun /* Parse a file containing a single int */
parse_int_file(int fatal,const char * fmt,...)160*4882a593Smuzhiyun static int parse_int_file(int fatal, const char *fmt, ...)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun 	va_list args;
163*4882a593Smuzhiyun 	char path[PATH_MAX];
164*4882a593Smuzhiyun 	FILE *filep;
165*4882a593Smuzhiyun 	int value;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	va_start(args, fmt);
168*4882a593Smuzhiyun 	vsnprintf(path, sizeof(path), fmt, args);
169*4882a593Smuzhiyun 	va_end(args);
170*4882a593Smuzhiyun 	if (fatal) {
171*4882a593Smuzhiyun 		filep = fopen_or_exit(path, "r");
172*4882a593Smuzhiyun 	} else {
173*4882a593Smuzhiyun 		filep = fopen(path, "r");
174*4882a593Smuzhiyun 		if (!filep)
175*4882a593Smuzhiyun 			return -1;
176*4882a593Smuzhiyun 	}
177*4882a593Smuzhiyun 	if (fscanf(filep, "%d", &value) != 1)
178*4882a593Smuzhiyun 		err(1, "%s: failed to parse number from file", path);
179*4882a593Smuzhiyun 	fclose(filep);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	return value;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
cpufreq_sysfs_present(void)184*4882a593Smuzhiyun int cpufreq_sysfs_present(void)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun 	DIR *dir;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	dir = opendir("/sys/devices/system/cpu/cpu0/cpufreq");
189*4882a593Smuzhiyun 	if (dir) {
190*4882a593Smuzhiyun 		closedir(dir);
191*4882a593Smuzhiyun 		return 1;
192*4882a593Smuzhiyun 	}
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	return 0;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
out_format_is_json(void)197*4882a593Smuzhiyun int out_format_is_json(void)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 	return out_format_json;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun 
get_stored_topology_info(int cpu,int * core_id,int * pkg_id,int * die_id)202*4882a593Smuzhiyun static int get_stored_topology_info(int cpu, int *core_id, int *pkg_id, int *die_id)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun 	const char *pathname = "/var/run/isst_cpu_topology.dat";
205*4882a593Smuzhiyun 	struct cpu_topology cpu_top;
206*4882a593Smuzhiyun 	FILE *fp;
207*4882a593Smuzhiyun 	int ret;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	fp = fopen(pathname, "rb");
210*4882a593Smuzhiyun 	if (!fp)
211*4882a593Smuzhiyun 		return -1;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	ret = fseek(fp, cpu * sizeof(cpu_top), SEEK_SET);
214*4882a593Smuzhiyun 	if (ret)
215*4882a593Smuzhiyun 		goto err_ret;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	ret = fread(&cpu_top, sizeof(cpu_top), 1, fp);
218*4882a593Smuzhiyun 	if (ret != 1) {
219*4882a593Smuzhiyun 		ret = -1;
220*4882a593Smuzhiyun 		goto err_ret;
221*4882a593Smuzhiyun 	}
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	*pkg_id = cpu_top.pkg_id;
224*4882a593Smuzhiyun 	*core_id = cpu_top.core_id;
225*4882a593Smuzhiyun 	*die_id = cpu_top.die_id;
226*4882a593Smuzhiyun 	ret = 0;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun err_ret:
229*4882a593Smuzhiyun 	fclose(fp);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	return ret;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
store_cpu_topology(void)234*4882a593Smuzhiyun static void store_cpu_topology(void)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun 	const char *pathname = "/var/run/isst_cpu_topology.dat";
237*4882a593Smuzhiyun 	FILE *fp;
238*4882a593Smuzhiyun 	int i;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	fp = fopen(pathname, "rb");
241*4882a593Smuzhiyun 	if (fp) {
242*4882a593Smuzhiyun 		/* Mapping already exists */
243*4882a593Smuzhiyun 		fclose(fp);
244*4882a593Smuzhiyun 		return;
245*4882a593Smuzhiyun 	}
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	fp = fopen(pathname, "wb");
248*4882a593Smuzhiyun 	if (!fp) {
249*4882a593Smuzhiyun 		fprintf(stderr, "Can't create file:%s\n", pathname);
250*4882a593Smuzhiyun 		return;
251*4882a593Smuzhiyun 	}
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	fprintf(stderr, "Caching topology information\n");
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	for (i = 0; i < topo_max_cpus; ++i) {
256*4882a593Smuzhiyun 		struct cpu_topology cpu_top;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 		cpu_top.core_id = parse_int_file(0,
259*4882a593Smuzhiyun 			"/sys/devices/system/cpu/cpu%d/topology/core_id", i);
260*4882a593Smuzhiyun 		if (cpu_top.core_id < 0)
261*4882a593Smuzhiyun 			cpu_top.core_id = -1;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 		cpu_top.pkg_id = parse_int_file(0,
264*4882a593Smuzhiyun 			"/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
265*4882a593Smuzhiyun 		if (cpu_top.pkg_id < 0)
266*4882a593Smuzhiyun 			cpu_top.pkg_id = -1;
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 		cpu_top.die_id = parse_int_file(0,
269*4882a593Smuzhiyun 			"/sys/devices/system/cpu/cpu%d/topology/die_id", i);
270*4882a593Smuzhiyun 		if (cpu_top.die_id < 0)
271*4882a593Smuzhiyun 			cpu_top.die_id = -1;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 		cpu_top.cpu = i;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 		if (fwrite(&cpu_top, sizeof(cpu_top), 1, fp) != 1) {
276*4882a593Smuzhiyun 			fprintf(stderr, "Can't write to:%s\n", pathname);
277*4882a593Smuzhiyun 			break;
278*4882a593Smuzhiyun 		}
279*4882a593Smuzhiyun 	}
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	fclose(fp);
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun 
get_physical_package_id(int cpu)284*4882a593Smuzhiyun int get_physical_package_id(int cpu)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun 	int ret;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	ret = parse_int_file(0,
289*4882a593Smuzhiyun 			"/sys/devices/system/cpu/cpu%d/topology/physical_package_id",
290*4882a593Smuzhiyun 			cpu);
291*4882a593Smuzhiyun 	if (ret < 0) {
292*4882a593Smuzhiyun 		int core_id, pkg_id, die_id;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 		ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
295*4882a593Smuzhiyun 		if (!ret)
296*4882a593Smuzhiyun 			return pkg_id;
297*4882a593Smuzhiyun 	}
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	return ret;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun 
get_physical_core_id(int cpu)302*4882a593Smuzhiyun int get_physical_core_id(int cpu)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	int ret;
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	ret = parse_int_file(0,
307*4882a593Smuzhiyun 			"/sys/devices/system/cpu/cpu%d/topology/core_id",
308*4882a593Smuzhiyun 			cpu);
309*4882a593Smuzhiyun 	if (ret < 0) {
310*4882a593Smuzhiyun 		int core_id, pkg_id, die_id;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 		ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
313*4882a593Smuzhiyun 		if (!ret)
314*4882a593Smuzhiyun 			return core_id;
315*4882a593Smuzhiyun 	}
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	return ret;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun 
get_physical_die_id(int cpu)320*4882a593Smuzhiyun int get_physical_die_id(int cpu)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun 	int ret;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	ret = parse_int_file(0,
325*4882a593Smuzhiyun 			"/sys/devices/system/cpu/cpu%d/topology/die_id",
326*4882a593Smuzhiyun 			cpu);
327*4882a593Smuzhiyun 	if (ret < 0) {
328*4882a593Smuzhiyun 		int core_id, pkg_id, die_id;
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 		ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
331*4882a593Smuzhiyun 		if (!ret)
332*4882a593Smuzhiyun 			return die_id;
333*4882a593Smuzhiyun 	}
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	if (ret < 0)
336*4882a593Smuzhiyun 		ret = 0;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	return ret;
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun 
get_cpufreq_base_freq(int cpu)341*4882a593Smuzhiyun int get_cpufreq_base_freq(int cpu)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun 	return parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", cpu);
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun 
get_topo_max_cpus(void)346*4882a593Smuzhiyun int get_topo_max_cpus(void)
347*4882a593Smuzhiyun {
348*4882a593Smuzhiyun 	return topo_max_cpus;
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun 
set_cpu_online_offline(int cpu,int state)351*4882a593Smuzhiyun static void set_cpu_online_offline(int cpu, int state)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun 	char buffer[128];
354*4882a593Smuzhiyun 	int fd, ret;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	snprintf(buffer, sizeof(buffer),
357*4882a593Smuzhiyun 		 "/sys/devices/system/cpu/cpu%d/online", cpu);
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	fd = open(buffer, O_WRONLY);
360*4882a593Smuzhiyun 	if (fd < 0) {
361*4882a593Smuzhiyun 		if (!cpu && state) {
362*4882a593Smuzhiyun 			fprintf(stderr, "This system is not configured for CPU 0 online/offline\n");
363*4882a593Smuzhiyun 			fprintf(stderr, "Ignoring online request for CPU 0 as this is already online\n");
364*4882a593Smuzhiyun 			return;
365*4882a593Smuzhiyun 		}
366*4882a593Smuzhiyun 		err(-1, "%s open failed", buffer);
367*4882a593Smuzhiyun 	}
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	if (state)
370*4882a593Smuzhiyun 		ret = write(fd, "1\n", 2);
371*4882a593Smuzhiyun 	else
372*4882a593Smuzhiyun 		ret = write(fd, "0\n", 2);
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	if (ret == -1)
375*4882a593Smuzhiyun 		perror("Online/Offline: Operation failed\n");
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	close(fd);
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun #define MAX_PACKAGE_COUNT 8
381*4882a593Smuzhiyun #define MAX_DIE_PER_PACKAGE 2
for_each_online_package_in_set(void (* callback)(int,void *,void *,void *,void *),void * arg1,void * arg2,void * arg3,void * arg4)382*4882a593Smuzhiyun static void for_each_online_package_in_set(void (*callback)(int, void *, void *,
383*4882a593Smuzhiyun 							    void *, void *),
384*4882a593Smuzhiyun 					   void *arg1, void *arg2, void *arg3,
385*4882a593Smuzhiyun 					   void *arg4)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun 	int max_packages[MAX_PACKAGE_COUNT * MAX_PACKAGE_COUNT];
388*4882a593Smuzhiyun 	int pkg_index = 0, i;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	memset(max_packages, 0xff, sizeof(max_packages));
391*4882a593Smuzhiyun 	for (i = 0; i < topo_max_cpus; ++i) {
392*4882a593Smuzhiyun 		int j, online, pkg_id, die_id = 0, skip = 0;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 		if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
395*4882a593Smuzhiyun 			continue;
396*4882a593Smuzhiyun 		if (i)
397*4882a593Smuzhiyun 			online = parse_int_file(
398*4882a593Smuzhiyun 				1, "/sys/devices/system/cpu/cpu%d/online", i);
399*4882a593Smuzhiyun 		else
400*4882a593Smuzhiyun 			online =
401*4882a593Smuzhiyun 				1; /* online entry for CPU 0 needs some special configs */
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 		die_id = get_physical_die_id(i);
404*4882a593Smuzhiyun 		if (die_id < 0)
405*4882a593Smuzhiyun 			die_id = 0;
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 		pkg_id = parse_int_file(0,
408*4882a593Smuzhiyun 			"/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
409*4882a593Smuzhiyun 		if (pkg_id < 0)
410*4882a593Smuzhiyun 			continue;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 		/* Create an unique id for package, die combination to store */
413*4882a593Smuzhiyun 		pkg_id = (MAX_PACKAGE_COUNT * pkg_id + die_id);
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 		for (j = 0; j < pkg_index; ++j) {
416*4882a593Smuzhiyun 			if (max_packages[j] == pkg_id) {
417*4882a593Smuzhiyun 				skip = 1;
418*4882a593Smuzhiyun 				break;
419*4882a593Smuzhiyun 			}
420*4882a593Smuzhiyun 		}
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 		if (!skip && online && callback) {
423*4882a593Smuzhiyun 			callback(i, arg1, arg2, arg3, arg4);
424*4882a593Smuzhiyun 			max_packages[pkg_index++] = pkg_id;
425*4882a593Smuzhiyun 		}
426*4882a593Smuzhiyun 	}
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun 
for_each_online_target_cpu_in_set(void (* callback)(int,void *,void *,void *,void *),void * arg1,void * arg2,void * arg3,void * arg4)429*4882a593Smuzhiyun static void for_each_online_target_cpu_in_set(
430*4882a593Smuzhiyun 	void (*callback)(int, void *, void *, void *, void *), void *arg1,
431*4882a593Smuzhiyun 	void *arg2, void *arg3, void *arg4)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun 	int i, found = 0;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	for (i = 0; i < topo_max_cpus; ++i) {
436*4882a593Smuzhiyun 		int online;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 		if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
439*4882a593Smuzhiyun 			continue;
440*4882a593Smuzhiyun 		if (i)
441*4882a593Smuzhiyun 			online = parse_int_file(
442*4882a593Smuzhiyun 				1, "/sys/devices/system/cpu/cpu%d/online", i);
443*4882a593Smuzhiyun 		else
444*4882a593Smuzhiyun 			online =
445*4882a593Smuzhiyun 				1; /* online entry for CPU 0 needs some special configs */
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 		if (online && callback) {
448*4882a593Smuzhiyun 			callback(i, arg1, arg2, arg3, arg4);
449*4882a593Smuzhiyun 			found = 1;
450*4882a593Smuzhiyun 		}
451*4882a593Smuzhiyun 	}
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	if (!found)
454*4882a593Smuzhiyun 		fprintf(stderr, "No valid CPU in the list\n");
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun #define BITMASK_SIZE 32
set_max_cpu_num(void)458*4882a593Smuzhiyun static void set_max_cpu_num(void)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun 	FILE *filep;
461*4882a593Smuzhiyun 	unsigned long dummy;
462*4882a593Smuzhiyun 	int i;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	topo_max_cpus = 0;
465*4882a593Smuzhiyun 	for (i = 0; i < 256; ++i) {
466*4882a593Smuzhiyun 		char path[256];
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 		snprintf(path, sizeof(path),
469*4882a593Smuzhiyun 			 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i);
470*4882a593Smuzhiyun 		filep = fopen(path, "r");
471*4882a593Smuzhiyun 		if (filep)
472*4882a593Smuzhiyun 			break;
473*4882a593Smuzhiyun 	}
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	if (!filep) {
476*4882a593Smuzhiyun 		fprintf(stderr, "Can't get max cpu number\n");
477*4882a593Smuzhiyun 		exit(0);
478*4882a593Smuzhiyun 	}
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun 	while (fscanf(filep, "%lx,", &dummy) == 1)
481*4882a593Smuzhiyun 		topo_max_cpus += BITMASK_SIZE;
482*4882a593Smuzhiyun 	fclose(filep);
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	debug_printf("max cpus %d\n", topo_max_cpus);
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun 
alloc_cpu_set(cpu_set_t ** cpu_set)487*4882a593Smuzhiyun size_t alloc_cpu_set(cpu_set_t **cpu_set)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun 	cpu_set_t *_cpu_set;
490*4882a593Smuzhiyun 	size_t size;
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	_cpu_set = CPU_ALLOC((topo_max_cpus + 1));
493*4882a593Smuzhiyun 	if (_cpu_set == NULL)
494*4882a593Smuzhiyun 		err(3, "CPU_ALLOC");
495*4882a593Smuzhiyun 	size = CPU_ALLOC_SIZE((topo_max_cpus + 1));
496*4882a593Smuzhiyun 	CPU_ZERO_S(size, _cpu_set);
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	*cpu_set = _cpu_set;
499*4882a593Smuzhiyun 	return size;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
free_cpu_set(cpu_set_t * cpu_set)502*4882a593Smuzhiyun void free_cpu_set(cpu_set_t *cpu_set)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun 	CPU_FREE(cpu_set);
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
508*4882a593Smuzhiyun static long long core_mask[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
set_cpu_present_cpu_mask(void)509*4882a593Smuzhiyun static void set_cpu_present_cpu_mask(void)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun 	size_t size;
512*4882a593Smuzhiyun 	DIR *dir;
513*4882a593Smuzhiyun 	int i;
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	size = alloc_cpu_set(&present_cpumask);
516*4882a593Smuzhiyun 	present_cpumask_size = size;
517*4882a593Smuzhiyun 	for (i = 0; i < topo_max_cpus; ++i) {
518*4882a593Smuzhiyun 		char buffer[256];
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 		snprintf(buffer, sizeof(buffer),
521*4882a593Smuzhiyun 			 "/sys/devices/system/cpu/cpu%d", i);
522*4882a593Smuzhiyun 		dir = opendir(buffer);
523*4882a593Smuzhiyun 		if (dir) {
524*4882a593Smuzhiyun 			int pkg_id, die_id;
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 			CPU_SET_S(i, size, present_cpumask);
527*4882a593Smuzhiyun 			die_id = get_physical_die_id(i);
528*4882a593Smuzhiyun 			if (die_id < 0)
529*4882a593Smuzhiyun 				die_id = 0;
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 			pkg_id = get_physical_package_id(i);
532*4882a593Smuzhiyun 			if (pkg_id < 0) {
533*4882a593Smuzhiyun 				fprintf(stderr, "Failed to get package id, CPU %d may be offline\n", i);
534*4882a593Smuzhiyun 				continue;
535*4882a593Smuzhiyun 			}
536*4882a593Smuzhiyun 			if (pkg_id < MAX_PACKAGE_COUNT &&
537*4882a593Smuzhiyun 			    die_id < MAX_DIE_PER_PACKAGE) {
538*4882a593Smuzhiyun 				int core_id = get_physical_core_id(i);
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 				cpu_cnt[pkg_id][die_id]++;
541*4882a593Smuzhiyun 				core_mask[pkg_id][die_id] |= (1ULL << core_id);
542*4882a593Smuzhiyun 			}
543*4882a593Smuzhiyun 		}
544*4882a593Smuzhiyun 		closedir(dir);
545*4882a593Smuzhiyun 	}
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun 
get_max_punit_core_id(int pkg_id,int die_id)548*4882a593Smuzhiyun int get_max_punit_core_id(int pkg_id, int die_id)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun 	int max_id = 0;
551*4882a593Smuzhiyun 	int i;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	for (i = 0; i < topo_max_cpus; ++i)
554*4882a593Smuzhiyun 	{
555*4882a593Smuzhiyun 		if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
556*4882a593Smuzhiyun 			continue;
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 		if (cpu_map[i].pkg_id == pkg_id &&
559*4882a593Smuzhiyun 			cpu_map[i].die_id == die_id &&
560*4882a593Smuzhiyun 			cpu_map[i].punit_cpu_core > max_id)
561*4882a593Smuzhiyun 			max_id = cpu_map[i].punit_cpu_core;
562*4882a593Smuzhiyun 	}
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	return max_id;
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun 
get_cpu_count(int pkg_id,int die_id)567*4882a593Smuzhiyun int get_cpu_count(int pkg_id, int die_id)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun 	if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE)
570*4882a593Smuzhiyun 		return cpu_cnt[pkg_id][die_id];
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 	return 0;
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun 
set_cpu_target_cpu_mask(void)575*4882a593Smuzhiyun static void set_cpu_target_cpu_mask(void)
576*4882a593Smuzhiyun {
577*4882a593Smuzhiyun 	size_t size;
578*4882a593Smuzhiyun 	int i;
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 	size = alloc_cpu_set(&target_cpumask);
581*4882a593Smuzhiyun 	target_cpumask_size = size;
582*4882a593Smuzhiyun 	for (i = 0; i < max_target_cpus; ++i) {
583*4882a593Smuzhiyun 		if (!CPU_ISSET_S(target_cpus[i], present_cpumask_size,
584*4882a593Smuzhiyun 				 present_cpumask))
585*4882a593Smuzhiyun 			continue;
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 		CPU_SET_S(target_cpus[i], size, target_cpumask);
588*4882a593Smuzhiyun 	}
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun 
create_cpu_map(void)591*4882a593Smuzhiyun static void create_cpu_map(void)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun 	const char *pathname = "/dev/isst_interface";
594*4882a593Smuzhiyun 	int i, fd = 0;
595*4882a593Smuzhiyun 	struct isst_if_cpu_maps map;
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	cpu_map = malloc(sizeof(*cpu_map) * topo_max_cpus);
598*4882a593Smuzhiyun 	if (!cpu_map)
599*4882a593Smuzhiyun 		err(3, "cpumap");
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	fd = open(pathname, O_RDWR);
602*4882a593Smuzhiyun 	if (fd < 0)
603*4882a593Smuzhiyun 		err(-1, "%s open failed", pathname);
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 	for (i = 0; i < topo_max_cpus; ++i) {
606*4882a593Smuzhiyun 		if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
607*4882a593Smuzhiyun 			continue;
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 		map.cmd_count = 1;
610*4882a593Smuzhiyun 		map.cpu_map[0].logical_cpu = i;
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 		debug_printf(" map logical_cpu:%d\n",
613*4882a593Smuzhiyun 			     map.cpu_map[0].logical_cpu);
614*4882a593Smuzhiyun 		if (ioctl(fd, ISST_IF_GET_PHY_ID, &map) == -1) {
615*4882a593Smuzhiyun 			perror("ISST_IF_GET_PHY_ID");
616*4882a593Smuzhiyun 			fprintf(outf, "Error: map logical_cpu:%d\n",
617*4882a593Smuzhiyun 				map.cpu_map[0].logical_cpu);
618*4882a593Smuzhiyun 			continue;
619*4882a593Smuzhiyun 		}
620*4882a593Smuzhiyun 		cpu_map[i].core_id = get_physical_core_id(i);
621*4882a593Smuzhiyun 		cpu_map[i].pkg_id = get_physical_package_id(i);
622*4882a593Smuzhiyun 		cpu_map[i].die_id = get_physical_die_id(i);
623*4882a593Smuzhiyun 		cpu_map[i].punit_cpu = map.cpu_map[0].physical_cpu;
624*4882a593Smuzhiyun 		cpu_map[i].punit_cpu_core = (map.cpu_map[0].physical_cpu >>
625*4882a593Smuzhiyun 					     1); // shift to get core id
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 		debug_printf(
628*4882a593Smuzhiyun 			"map logical_cpu:%d core: %d die:%d pkg:%d punit_cpu:%d punit_core:%d\n",
629*4882a593Smuzhiyun 			i, cpu_map[i].core_id, cpu_map[i].die_id,
630*4882a593Smuzhiyun 			cpu_map[i].pkg_id, cpu_map[i].punit_cpu,
631*4882a593Smuzhiyun 			cpu_map[i].punit_cpu_core);
632*4882a593Smuzhiyun 	}
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	if (fd)
635*4882a593Smuzhiyun 		close(fd);
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun 
find_logical_cpu(int pkg_id,int die_id,int punit_core_id)638*4882a593Smuzhiyun int find_logical_cpu(int pkg_id, int die_id, int punit_core_id)
639*4882a593Smuzhiyun {
640*4882a593Smuzhiyun 	int i;
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 	for (i = 0; i < topo_max_cpus; ++i) {
643*4882a593Smuzhiyun 		if (cpu_map[i].pkg_id == pkg_id &&
644*4882a593Smuzhiyun 		    cpu_map[i].die_id == die_id &&
645*4882a593Smuzhiyun 		    cpu_map[i].punit_cpu_core == punit_core_id)
646*4882a593Smuzhiyun 			return i;
647*4882a593Smuzhiyun 	}
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	return -EINVAL;
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun 
set_cpu_mask_from_punit_coremask(int cpu,unsigned long long core_mask,size_t core_cpumask_size,cpu_set_t * core_cpumask,int * cpu_cnt)652*4882a593Smuzhiyun void set_cpu_mask_from_punit_coremask(int cpu, unsigned long long core_mask,
653*4882a593Smuzhiyun 				      size_t core_cpumask_size,
654*4882a593Smuzhiyun 				      cpu_set_t *core_cpumask, int *cpu_cnt)
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun 	int i, cnt = 0;
657*4882a593Smuzhiyun 	int die_id, pkg_id;
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 	*cpu_cnt = 0;
660*4882a593Smuzhiyun 	die_id = get_physical_die_id(cpu);
661*4882a593Smuzhiyun 	pkg_id = get_physical_package_id(cpu);
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 	for (i = 0; i < 64; ++i) {
664*4882a593Smuzhiyun 		if (core_mask & BIT_ULL(i)) {
665*4882a593Smuzhiyun 			int j;
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun 			for (j = 0; j < topo_max_cpus; ++j) {
668*4882a593Smuzhiyun 				if (!CPU_ISSET_S(j, present_cpumask_size, present_cpumask))
669*4882a593Smuzhiyun 					continue;
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun 				if (cpu_map[j].pkg_id == pkg_id &&
672*4882a593Smuzhiyun 				    cpu_map[j].die_id == die_id &&
673*4882a593Smuzhiyun 				    cpu_map[j].punit_cpu_core == i) {
674*4882a593Smuzhiyun 					CPU_SET_S(j, core_cpumask_size,
675*4882a593Smuzhiyun 						  core_cpumask);
676*4882a593Smuzhiyun 					++cnt;
677*4882a593Smuzhiyun 				}
678*4882a593Smuzhiyun 			}
679*4882a593Smuzhiyun 		}
680*4882a593Smuzhiyun 	}
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	*cpu_cnt = cnt;
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun 
find_phy_core_num(int logical_cpu)685*4882a593Smuzhiyun int find_phy_core_num(int logical_cpu)
686*4882a593Smuzhiyun {
687*4882a593Smuzhiyun 	if (logical_cpu < topo_max_cpus)
688*4882a593Smuzhiyun 		return cpu_map[logical_cpu].punit_cpu_core;
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun 	return -EINVAL;
691*4882a593Smuzhiyun }
692*4882a593Smuzhiyun 
isst_send_mmio_command(unsigned int cpu,unsigned int reg,int write,unsigned int * value)693*4882a593Smuzhiyun static int isst_send_mmio_command(unsigned int cpu, unsigned int reg, int write,
694*4882a593Smuzhiyun 				  unsigned int *value)
695*4882a593Smuzhiyun {
696*4882a593Smuzhiyun 	struct isst_if_io_regs io_regs;
697*4882a593Smuzhiyun 	const char *pathname = "/dev/isst_interface";
698*4882a593Smuzhiyun 	int cmd;
699*4882a593Smuzhiyun 	int fd;
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun 	fd = open(pathname, O_RDWR);
704*4882a593Smuzhiyun 	if (fd < 0)
705*4882a593Smuzhiyun 		err(-1, "%s open failed", pathname);
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun 	io_regs.req_count = 1;
708*4882a593Smuzhiyun 	io_regs.io_reg[0].logical_cpu = cpu;
709*4882a593Smuzhiyun 	io_regs.io_reg[0].reg = reg;
710*4882a593Smuzhiyun 	cmd = ISST_IF_IO_CMD;
711*4882a593Smuzhiyun 	if (write) {
712*4882a593Smuzhiyun 		io_regs.io_reg[0].read_write = 1;
713*4882a593Smuzhiyun 		io_regs.io_reg[0].value = *value;
714*4882a593Smuzhiyun 	} else {
715*4882a593Smuzhiyun 		io_regs.io_reg[0].read_write = 0;
716*4882a593Smuzhiyun 	}
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	if (ioctl(fd, cmd, &io_regs) == -1) {
719*4882a593Smuzhiyun 		if (errno == ENOTTY) {
720*4882a593Smuzhiyun 			perror("ISST_IF_IO_COMMAND\n");
721*4882a593Smuzhiyun 			fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n");
722*4882a593Smuzhiyun 			exit(0);
723*4882a593Smuzhiyun 		}
724*4882a593Smuzhiyun 		fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
725*4882a593Smuzhiyun 			cpu, reg, write);
726*4882a593Smuzhiyun 	} else {
727*4882a593Smuzhiyun 		if (!write)
728*4882a593Smuzhiyun 			*value = io_regs.io_reg[0].value;
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun 		debug_printf(
731*4882a593Smuzhiyun 			"mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
732*4882a593Smuzhiyun 			cpu, reg, write, *value);
733*4882a593Smuzhiyun 	}
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 	close(fd);
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 	return 0;
738*4882a593Smuzhiyun }
739*4882a593Smuzhiyun 
isst_send_mbox_command(unsigned int cpu,unsigned char command,unsigned char sub_command,unsigned int parameter,unsigned int req_data,unsigned int * resp)740*4882a593Smuzhiyun int isst_send_mbox_command(unsigned int cpu, unsigned char command,
741*4882a593Smuzhiyun 			   unsigned char sub_command, unsigned int parameter,
742*4882a593Smuzhiyun 			   unsigned int req_data, unsigned int *resp)
743*4882a593Smuzhiyun {
744*4882a593Smuzhiyun 	const char *pathname = "/dev/isst_interface";
745*4882a593Smuzhiyun 	int fd, retry;
746*4882a593Smuzhiyun 	struct isst_if_mbox_cmds mbox_cmds = { 0 };
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun 	debug_printf(
749*4882a593Smuzhiyun 		"mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
750*4882a593Smuzhiyun 		cpu, command, sub_command, parameter, req_data);
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun 	if (!is_skx_based_platform() && command == CONFIG_CLOS &&
753*4882a593Smuzhiyun 	    sub_command != CLOS_PM_QOS_CONFIG) {
754*4882a593Smuzhiyun 		unsigned int value;
755*4882a593Smuzhiyun 		int write = 0;
756*4882a593Smuzhiyun 		int clos_id, core_id, ret = 0;
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 		debug_printf("CPU %d\n", cpu);
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun 		if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
761*4882a593Smuzhiyun 			value = req_data;
762*4882a593Smuzhiyun 			write = 1;
763*4882a593Smuzhiyun 		}
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 		switch (sub_command) {
766*4882a593Smuzhiyun 		case CLOS_PQR_ASSOC:
767*4882a593Smuzhiyun 			core_id = parameter & 0xff;
768*4882a593Smuzhiyun 			ret = isst_send_mmio_command(
769*4882a593Smuzhiyun 				cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
770*4882a593Smuzhiyun 				&value);
771*4882a593Smuzhiyun 			if (!ret && !write)
772*4882a593Smuzhiyun 				*resp = value;
773*4882a593Smuzhiyun 			break;
774*4882a593Smuzhiyun 		case CLOS_PM_CLOS:
775*4882a593Smuzhiyun 			clos_id = parameter & 0x03;
776*4882a593Smuzhiyun 			ret = isst_send_mmio_command(
777*4882a593Smuzhiyun 				cpu, PM_CLOS_OFFSET + clos_id * 4, write,
778*4882a593Smuzhiyun 				&value);
779*4882a593Smuzhiyun 			if (!ret && !write)
780*4882a593Smuzhiyun 				*resp = value;
781*4882a593Smuzhiyun 			break;
782*4882a593Smuzhiyun 		case CLOS_STATUS:
783*4882a593Smuzhiyun 			break;
784*4882a593Smuzhiyun 		default:
785*4882a593Smuzhiyun 			break;
786*4882a593Smuzhiyun 		}
787*4882a593Smuzhiyun 		return ret;
788*4882a593Smuzhiyun 	}
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun 	mbox_cmds.cmd_count = 1;
791*4882a593Smuzhiyun 	mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
792*4882a593Smuzhiyun 	mbox_cmds.mbox_cmd[0].command = command;
793*4882a593Smuzhiyun 	mbox_cmds.mbox_cmd[0].sub_command = sub_command;
794*4882a593Smuzhiyun 	mbox_cmds.mbox_cmd[0].parameter = parameter;
795*4882a593Smuzhiyun 	mbox_cmds.mbox_cmd[0].req_data = req_data;
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun 	if (mbox_delay)
798*4882a593Smuzhiyun 		usleep(mbox_delay * 1000);
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun 	fd = open(pathname, O_RDWR);
801*4882a593Smuzhiyun 	if (fd < 0)
802*4882a593Smuzhiyun 		err(-1, "%s open failed", pathname);
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun 	retry = mbox_retries;
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 	do {
807*4882a593Smuzhiyun 		if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
808*4882a593Smuzhiyun 			if (errno == ENOTTY) {
809*4882a593Smuzhiyun 				perror("ISST_IF_MBOX_COMMAND\n");
810*4882a593Smuzhiyun 				fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
811*4882a593Smuzhiyun 				exit(0);
812*4882a593Smuzhiyun 			}
813*4882a593Smuzhiyun 			debug_printf(
814*4882a593Smuzhiyun 				"Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",
815*4882a593Smuzhiyun 				cpu, command, sub_command, parameter, req_data, errno);
816*4882a593Smuzhiyun 			--retry;
817*4882a593Smuzhiyun 		} else {
818*4882a593Smuzhiyun 			*resp = mbox_cmds.mbox_cmd[0].resp_data;
819*4882a593Smuzhiyun 			debug_printf(
820*4882a593Smuzhiyun 				"mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
821*4882a593Smuzhiyun 				cpu, command, sub_command, parameter, req_data, *resp);
822*4882a593Smuzhiyun 			break;
823*4882a593Smuzhiyun 		}
824*4882a593Smuzhiyun 	} while (retry);
825*4882a593Smuzhiyun 
826*4882a593Smuzhiyun 	close(fd);
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun 	if (!retry) {
829*4882a593Smuzhiyun 		debug_printf("Failed mbox command even after retries\n");
830*4882a593Smuzhiyun 		return -1;
831*4882a593Smuzhiyun 
832*4882a593Smuzhiyun 	}
833*4882a593Smuzhiyun 	return 0;
834*4882a593Smuzhiyun }
835*4882a593Smuzhiyun 
isst_send_msr_command(unsigned int cpu,unsigned int msr,int write,unsigned long long * req_resp)836*4882a593Smuzhiyun int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write,
837*4882a593Smuzhiyun 			  unsigned long long *req_resp)
838*4882a593Smuzhiyun {
839*4882a593Smuzhiyun 	struct isst_if_msr_cmds msr_cmds;
840*4882a593Smuzhiyun 	const char *pathname = "/dev/isst_interface";
841*4882a593Smuzhiyun 	int fd;
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun 	fd = open(pathname, O_RDWR);
844*4882a593Smuzhiyun 	if (fd < 0)
845*4882a593Smuzhiyun 		err(-1, "%s open failed", pathname);
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 	msr_cmds.cmd_count = 1;
848*4882a593Smuzhiyun 	msr_cmds.msr_cmd[0].logical_cpu = cpu;
849*4882a593Smuzhiyun 	msr_cmds.msr_cmd[0].msr = msr;
850*4882a593Smuzhiyun 	msr_cmds.msr_cmd[0].read_write = write;
851*4882a593Smuzhiyun 	if (write)
852*4882a593Smuzhiyun 		msr_cmds.msr_cmd[0].data = *req_resp;
853*4882a593Smuzhiyun 
854*4882a593Smuzhiyun 	if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
855*4882a593Smuzhiyun 		perror("ISST_IF_MSR_COMMAND");
856*4882a593Smuzhiyun 		fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
857*4882a593Smuzhiyun 			cpu, msr, write);
858*4882a593Smuzhiyun 	} else {
859*4882a593Smuzhiyun 		if (!write)
860*4882a593Smuzhiyun 			*req_resp = msr_cmds.msr_cmd[0].data;
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun 		debug_printf(
863*4882a593Smuzhiyun 			"msr_cmd response: cpu:%d msr:%x rd_write:%x resp:%llx %llx\n",
864*4882a593Smuzhiyun 			cpu, msr, write, *req_resp, msr_cmds.msr_cmd[0].data);
865*4882a593Smuzhiyun 	}
866*4882a593Smuzhiyun 
867*4882a593Smuzhiyun 	close(fd);
868*4882a593Smuzhiyun 
869*4882a593Smuzhiyun 	return 0;
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun 
isst_fill_platform_info(void)872*4882a593Smuzhiyun static int isst_fill_platform_info(void)
873*4882a593Smuzhiyun {
874*4882a593Smuzhiyun 	const char *pathname = "/dev/isst_interface";
875*4882a593Smuzhiyun 	int fd;
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun 	fd = open(pathname, O_RDWR);
878*4882a593Smuzhiyun 	if (fd < 0)
879*4882a593Smuzhiyun 		err(-1, "%s open failed", pathname);
880*4882a593Smuzhiyun 
881*4882a593Smuzhiyun 	if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &isst_platform_info) == -1) {
882*4882a593Smuzhiyun 		perror("ISST_IF_GET_PLATFORM_INFO");
883*4882a593Smuzhiyun 		close(fd);
884*4882a593Smuzhiyun 		return -1;
885*4882a593Smuzhiyun 	}
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	close(fd);
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun 	if (isst_platform_info.api_version > supported_api_ver) {
890*4882a593Smuzhiyun 		printf("Incompatible API versions; Upgrade of tool is required\n");
891*4882a593Smuzhiyun 		return -1;
892*4882a593Smuzhiyun 	}
893*4882a593Smuzhiyun 	return 0;
894*4882a593Smuzhiyun }
895*4882a593Smuzhiyun 
isst_print_extended_platform_info(void)896*4882a593Smuzhiyun static void isst_print_extended_platform_info(void)
897*4882a593Smuzhiyun {
898*4882a593Smuzhiyun 	int cp_state, cp_cap, fact_support = 0, pbf_support = 0;
899*4882a593Smuzhiyun 	struct isst_pkg_ctdp_level_info ctdp_level;
900*4882a593Smuzhiyun 	struct isst_pkg_ctdp pkg_dev;
901*4882a593Smuzhiyun 	int ret, i, j;
902*4882a593Smuzhiyun 	FILE *filep;
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun 	for (i = 0; i < 256; ++i) {
905*4882a593Smuzhiyun 		char path[256];
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun 		snprintf(path, sizeof(path),
908*4882a593Smuzhiyun 			 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i);
909*4882a593Smuzhiyun 		filep = fopen(path, "r");
910*4882a593Smuzhiyun 		if (filep)
911*4882a593Smuzhiyun 			break;
912*4882a593Smuzhiyun 	}
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun 	if (!filep)
915*4882a593Smuzhiyun 		return;
916*4882a593Smuzhiyun 
917*4882a593Smuzhiyun 	fclose(filep);
918*4882a593Smuzhiyun 
919*4882a593Smuzhiyun 	ret = isst_get_ctdp_levels(i, &pkg_dev);
920*4882a593Smuzhiyun 	if (ret)
921*4882a593Smuzhiyun 		return;
922*4882a593Smuzhiyun 
923*4882a593Smuzhiyun 	if (pkg_dev.enabled) {
924*4882a593Smuzhiyun 		fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is supported\n");
925*4882a593Smuzhiyun 	} else {
926*4882a593Smuzhiyun 		fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is not supported\n");
927*4882a593Smuzhiyun 		fprintf(outf, "Only performance level 0 (base level) is present\n");
928*4882a593Smuzhiyun 	}
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun 	if (pkg_dev.locked)
931*4882a593Smuzhiyun 		fprintf(outf, "TDP level change control is locked\n");
932*4882a593Smuzhiyun 	else
933*4882a593Smuzhiyun 		fprintf(outf, "TDP level change control is unlocked, max level: %d \n", pkg_dev.levels);
934*4882a593Smuzhiyun 
935*4882a593Smuzhiyun 	for (j = 0; j <= pkg_dev.levels; ++j) {
936*4882a593Smuzhiyun 		ret = isst_get_ctdp_control(i, j, &ctdp_level);
937*4882a593Smuzhiyun 		if (ret)
938*4882a593Smuzhiyun 			continue;
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun 		if (!fact_support && ctdp_level.fact_support)
941*4882a593Smuzhiyun 			fact_support = 1;
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 		if (!pbf_support && ctdp_level.pbf_support)
944*4882a593Smuzhiyun 			pbf_support = 1;
945*4882a593Smuzhiyun 	}
946*4882a593Smuzhiyun 
947*4882a593Smuzhiyun 	if (fact_support)
948*4882a593Smuzhiyun 		fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is supported\n");
949*4882a593Smuzhiyun 	else
950*4882a593Smuzhiyun 		fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is not supported\n");
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun 	if (pbf_support)
953*4882a593Smuzhiyun 		fprintf(outf, "Intel(R) SST-BF (feature base-freq) is supported\n");
954*4882a593Smuzhiyun 	else
955*4882a593Smuzhiyun 		fprintf(outf, "Intel(R) SST-BF (feature base-freq) is not supported\n");
956*4882a593Smuzhiyun 
957*4882a593Smuzhiyun 	ret = isst_read_pm_config(i, &cp_state, &cp_cap);
958*4882a593Smuzhiyun 	if (cp_cap)
959*4882a593Smuzhiyun 		fprintf(outf, "Intel(R) SST-CP (feature core-power) is supported\n");
960*4882a593Smuzhiyun 	else
961*4882a593Smuzhiyun 		fprintf(outf, "Intel(R) SST-CP (feature core-power) is not supported\n");
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun 
isst_print_platform_information(void)964*4882a593Smuzhiyun static void isst_print_platform_information(void)
965*4882a593Smuzhiyun {
966*4882a593Smuzhiyun 	struct isst_if_platform_info platform_info;
967*4882a593Smuzhiyun 	const char *pathname = "/dev/isst_interface";
968*4882a593Smuzhiyun 	int fd;
969*4882a593Smuzhiyun 
970*4882a593Smuzhiyun 	if (is_clx_n_platform()) {
971*4882a593Smuzhiyun 		fprintf(stderr, "\nThis option in not supported on this platform\n");
972*4882a593Smuzhiyun 		exit(0);
973*4882a593Smuzhiyun 	}
974*4882a593Smuzhiyun 
975*4882a593Smuzhiyun 	fd = open(pathname, O_RDWR);
976*4882a593Smuzhiyun 	if (fd < 0)
977*4882a593Smuzhiyun 		err(-1, "%s open failed", pathname);
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun 	if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &platform_info) == -1) {
980*4882a593Smuzhiyun 		perror("ISST_IF_GET_PLATFORM_INFO");
981*4882a593Smuzhiyun 	} else {
982*4882a593Smuzhiyun 		fprintf(outf, "Platform: API version : %d\n",
983*4882a593Smuzhiyun 			platform_info.api_version);
984*4882a593Smuzhiyun 		fprintf(outf, "Platform: Driver version : %d\n",
985*4882a593Smuzhiyun 			platform_info.driver_version);
986*4882a593Smuzhiyun 		fprintf(outf, "Platform: mbox supported : %d\n",
987*4882a593Smuzhiyun 			platform_info.mbox_supported);
988*4882a593Smuzhiyun 		fprintf(outf, "Platform: mmio supported : %d\n",
989*4882a593Smuzhiyun 			platform_info.mmio_supported);
990*4882a593Smuzhiyun 		isst_print_extended_platform_info();
991*4882a593Smuzhiyun 	}
992*4882a593Smuzhiyun 
993*4882a593Smuzhiyun 	close(fd);
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun 	exit(0);
996*4882a593Smuzhiyun }
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun static char *local_str0, *local_str1;
exec_on_get_ctdp_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)999*4882a593Smuzhiyun static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1000*4882a593Smuzhiyun 				 void *arg4)
1001*4882a593Smuzhiyun {
1002*4882a593Smuzhiyun 	int (*fn_ptr)(int cpu, void *arg);
1003*4882a593Smuzhiyun 	int ret;
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun 	fn_ptr = arg1;
1006*4882a593Smuzhiyun 	ret = fn_ptr(cpu, arg2);
1007*4882a593Smuzhiyun 	if (ret)
1008*4882a593Smuzhiyun 		isst_display_error_info_message(1, "get_tdp_* failed", 0, 0);
1009*4882a593Smuzhiyun 	else
1010*4882a593Smuzhiyun 		isst_ctdp_display_core_info(cpu, outf, arg3,
1011*4882a593Smuzhiyun 					    *(unsigned int *)arg4,
1012*4882a593Smuzhiyun 					    local_str0, local_str1);
1013*4882a593Smuzhiyun }
1014*4882a593Smuzhiyun 
1015*4882a593Smuzhiyun #define _get_tdp_level(desc, suffix, object, help, str0, str1)			\
1016*4882a593Smuzhiyun 	static void get_tdp_##object(int arg)                                    \
1017*4882a593Smuzhiyun 	{                                                                         \
1018*4882a593Smuzhiyun 		struct isst_pkg_ctdp ctdp;                                        \
1019*4882a593Smuzhiyun \
1020*4882a593Smuzhiyun 		if (cmd_help) {                                                   \
1021*4882a593Smuzhiyun 			fprintf(stderr,                                           \
1022*4882a593Smuzhiyun 				"Print %s [No command arguments are required]\n", \
1023*4882a593Smuzhiyun 				help);                                            \
1024*4882a593Smuzhiyun 			exit(0);                                                  \
1025*4882a593Smuzhiyun 		}                                                                 \
1026*4882a593Smuzhiyun 		local_str0 = str0;						  \
1027*4882a593Smuzhiyun 		local_str1 = str1;						  \
1028*4882a593Smuzhiyun 		isst_ctdp_display_information_start(outf);                        \
1029*4882a593Smuzhiyun 		if (max_target_cpus)                                              \
1030*4882a593Smuzhiyun 			for_each_online_target_cpu_in_set(                        \
1031*4882a593Smuzhiyun 				exec_on_get_ctdp_cpu, isst_get_ctdp_##suffix,     \
1032*4882a593Smuzhiyun 				&ctdp, desc, &ctdp.object);                       \
1033*4882a593Smuzhiyun 		else                                                              \
1034*4882a593Smuzhiyun 			for_each_online_package_in_set(exec_on_get_ctdp_cpu,      \
1035*4882a593Smuzhiyun 						       isst_get_ctdp_##suffix,    \
1036*4882a593Smuzhiyun 						       &ctdp, desc,               \
1037*4882a593Smuzhiyun 						       &ctdp.object);             \
1038*4882a593Smuzhiyun 		isst_ctdp_display_information_end(outf);                          \
1039*4882a593Smuzhiyun 	}
1040*4882a593Smuzhiyun 
1041*4882a593Smuzhiyun _get_tdp_level("get-config-levels", levels, levels, "Max TDP level", NULL, NULL);
1042*4882a593Smuzhiyun _get_tdp_level("get-config-version", levels, version, "TDP version", NULL, NULL);
1043*4882a593Smuzhiyun _get_tdp_level("get-config-enabled", levels, enabled, "perf-profile enable status", "disabled", "enabled");
1044*4882a593Smuzhiyun _get_tdp_level("get-config-current_level", levels, current_level,
1045*4882a593Smuzhiyun 	       "Current TDP Level", NULL, NULL);
1046*4882a593Smuzhiyun _get_tdp_level("get-lock-status", levels, locked, "TDP lock status", "unlocked", "locked");
1047*4882a593Smuzhiyun 
1048*4882a593Smuzhiyun struct isst_pkg_ctdp clx_n_pkg_dev;
1049*4882a593Smuzhiyun 
clx_n_get_base_ratio(void)1050*4882a593Smuzhiyun static int clx_n_get_base_ratio(void)
1051*4882a593Smuzhiyun {
1052*4882a593Smuzhiyun 	FILE *fp;
1053*4882a593Smuzhiyun 	char *begin, *end, *line = NULL;
1054*4882a593Smuzhiyun 	char number[5];
1055*4882a593Smuzhiyun 	float value = 0;
1056*4882a593Smuzhiyun 	size_t n = 0;
1057*4882a593Smuzhiyun 
1058*4882a593Smuzhiyun 	fp = fopen("/proc/cpuinfo", "r");
1059*4882a593Smuzhiyun 	if (!fp)
1060*4882a593Smuzhiyun 		err(-1, "cannot open /proc/cpuinfo\n");
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun 	while (getline(&line, &n, fp) > 0) {
1063*4882a593Smuzhiyun 		if (strstr(line, "model name")) {
1064*4882a593Smuzhiyun 			/* this is true for CascadeLake-N */
1065*4882a593Smuzhiyun 			begin = strstr(line, "@ ") + 2;
1066*4882a593Smuzhiyun 			end = strstr(line, "GHz");
1067*4882a593Smuzhiyun 			strncpy(number, begin, end - begin);
1068*4882a593Smuzhiyun 			value = atof(number) * 10;
1069*4882a593Smuzhiyun 			break;
1070*4882a593Smuzhiyun 		}
1071*4882a593Smuzhiyun 	}
1072*4882a593Smuzhiyun 	free(line);
1073*4882a593Smuzhiyun 	fclose(fp);
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun 	return (int)(value);
1076*4882a593Smuzhiyun }
1077*4882a593Smuzhiyun 
clx_n_config(int cpu)1078*4882a593Smuzhiyun static int clx_n_config(int cpu)
1079*4882a593Smuzhiyun {
1080*4882a593Smuzhiyun 	int i, ret, pkg_id, die_id;
1081*4882a593Smuzhiyun 	unsigned long cpu_bf;
1082*4882a593Smuzhiyun 	struct isst_pkg_ctdp_level_info *ctdp_level;
1083*4882a593Smuzhiyun 	struct isst_pbf_info *pbf_info;
1084*4882a593Smuzhiyun 
1085*4882a593Smuzhiyun 	ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
1086*4882a593Smuzhiyun 	pbf_info = &ctdp_level->pbf_info;
1087*4882a593Smuzhiyun 	ctdp_level->core_cpumask_size =
1088*4882a593Smuzhiyun 			alloc_cpu_set(&ctdp_level->core_cpumask);
1089*4882a593Smuzhiyun 
1090*4882a593Smuzhiyun 	/* find the frequency base ratio */
1091*4882a593Smuzhiyun 	ctdp_level->tdp_ratio = clx_n_get_base_ratio();
1092*4882a593Smuzhiyun 	if (ctdp_level->tdp_ratio == 0) {
1093*4882a593Smuzhiyun 		debug_printf("CLX: cn base ratio is zero\n");
1094*4882a593Smuzhiyun 		ret = -1;
1095*4882a593Smuzhiyun 		goto error_ret;
1096*4882a593Smuzhiyun 	}
1097*4882a593Smuzhiyun 
1098*4882a593Smuzhiyun 	/* find the high and low priority frequencies */
1099*4882a593Smuzhiyun 	pbf_info->p1_high = 0;
1100*4882a593Smuzhiyun 	pbf_info->p1_low = ~0;
1101*4882a593Smuzhiyun 
1102*4882a593Smuzhiyun 	pkg_id = get_physical_package_id(cpu);
1103*4882a593Smuzhiyun 	die_id = get_physical_die_id(cpu);
1104*4882a593Smuzhiyun 
1105*4882a593Smuzhiyun 	for (i = 0; i < topo_max_cpus; i++) {
1106*4882a593Smuzhiyun 		if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
1107*4882a593Smuzhiyun 			continue;
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun 		if (pkg_id != get_physical_package_id(i) ||
1110*4882a593Smuzhiyun 		    die_id != get_physical_die_id(i))
1111*4882a593Smuzhiyun 			continue;
1112*4882a593Smuzhiyun 
1113*4882a593Smuzhiyun 		CPU_SET_S(i, ctdp_level->core_cpumask_size,
1114*4882a593Smuzhiyun 			  ctdp_level->core_cpumask);
1115*4882a593Smuzhiyun 
1116*4882a593Smuzhiyun 		cpu_bf = parse_int_file(1,
1117*4882a593Smuzhiyun 			"/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency",
1118*4882a593Smuzhiyun 					i);
1119*4882a593Smuzhiyun 		if (cpu_bf > pbf_info->p1_high)
1120*4882a593Smuzhiyun 			pbf_info->p1_high = cpu_bf;
1121*4882a593Smuzhiyun 		if (cpu_bf < pbf_info->p1_low)
1122*4882a593Smuzhiyun 			pbf_info->p1_low = cpu_bf;
1123*4882a593Smuzhiyun 	}
1124*4882a593Smuzhiyun 
1125*4882a593Smuzhiyun 	if (pbf_info->p1_high == ~0UL) {
1126*4882a593Smuzhiyun 		debug_printf("CLX: maximum base frequency not set\n");
1127*4882a593Smuzhiyun 		ret = -1;
1128*4882a593Smuzhiyun 		goto error_ret;
1129*4882a593Smuzhiyun 	}
1130*4882a593Smuzhiyun 
1131*4882a593Smuzhiyun 	if (pbf_info->p1_low == 0) {
1132*4882a593Smuzhiyun 		debug_printf("CLX: minimum base frequency not set\n");
1133*4882a593Smuzhiyun 		ret = -1;
1134*4882a593Smuzhiyun 		goto error_ret;
1135*4882a593Smuzhiyun 	}
1136*4882a593Smuzhiyun 
1137*4882a593Smuzhiyun 	/* convert frequencies back to ratios */
1138*4882a593Smuzhiyun 	pbf_info->p1_high = pbf_info->p1_high / 100000;
1139*4882a593Smuzhiyun 	pbf_info->p1_low = pbf_info->p1_low / 100000;
1140*4882a593Smuzhiyun 
1141*4882a593Smuzhiyun 	/* create high priority cpu mask */
1142*4882a593Smuzhiyun 	pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
1143*4882a593Smuzhiyun 	for (i = 0; i < topo_max_cpus; i++) {
1144*4882a593Smuzhiyun 		if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
1145*4882a593Smuzhiyun 			continue;
1146*4882a593Smuzhiyun 
1147*4882a593Smuzhiyun 		if (pkg_id != get_physical_package_id(i) ||
1148*4882a593Smuzhiyun 		    die_id != get_physical_die_id(i))
1149*4882a593Smuzhiyun 			continue;
1150*4882a593Smuzhiyun 
1151*4882a593Smuzhiyun 		cpu_bf = parse_int_file(1,
1152*4882a593Smuzhiyun 			"/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency",
1153*4882a593Smuzhiyun 					i);
1154*4882a593Smuzhiyun 		cpu_bf = cpu_bf / 100000;
1155*4882a593Smuzhiyun 		if (cpu_bf == pbf_info->p1_high)
1156*4882a593Smuzhiyun 			CPU_SET_S(i, pbf_info->core_cpumask_size,
1157*4882a593Smuzhiyun 				  pbf_info->core_cpumask);
1158*4882a593Smuzhiyun 	}
1159*4882a593Smuzhiyun 
1160*4882a593Smuzhiyun 	/* extra ctdp & pbf struct parameters */
1161*4882a593Smuzhiyun 	ctdp_level->processed = 1;
1162*4882a593Smuzhiyun 	ctdp_level->pbf_support = 1; /* PBF is always supported and enabled */
1163*4882a593Smuzhiyun 	ctdp_level->pbf_enabled = 1;
1164*4882a593Smuzhiyun 	ctdp_level->fact_support = 0; /* FACT is never supported */
1165*4882a593Smuzhiyun 	ctdp_level->fact_enabled = 0;
1166*4882a593Smuzhiyun 
1167*4882a593Smuzhiyun 	return 0;
1168*4882a593Smuzhiyun 
1169*4882a593Smuzhiyun error_ret:
1170*4882a593Smuzhiyun 	free_cpu_set(ctdp_level->core_cpumask);
1171*4882a593Smuzhiyun 	return ret;
1172*4882a593Smuzhiyun }
1173*4882a593Smuzhiyun 
dump_clx_n_config_for_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)1174*4882a593Smuzhiyun static void dump_clx_n_config_for_cpu(int cpu, void *arg1, void *arg2,
1175*4882a593Smuzhiyun 				   void *arg3, void *arg4)
1176*4882a593Smuzhiyun {
1177*4882a593Smuzhiyun 	int ret;
1178*4882a593Smuzhiyun 
1179*4882a593Smuzhiyun 	if (tdp_level != 0xff && tdp_level != 0) {
1180*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Invalid level", 1, tdp_level);
1181*4882a593Smuzhiyun 		exit(0);
1182*4882a593Smuzhiyun 	}
1183*4882a593Smuzhiyun 
1184*4882a593Smuzhiyun 	ret = clx_n_config(cpu);
1185*4882a593Smuzhiyun 	if (ret) {
1186*4882a593Smuzhiyun 		debug_printf("clx_n_config failed");
1187*4882a593Smuzhiyun 	} else {
1188*4882a593Smuzhiyun 		struct isst_pkg_ctdp_level_info *ctdp_level;
1189*4882a593Smuzhiyun 		struct isst_pbf_info *pbf_info;
1190*4882a593Smuzhiyun 
1191*4882a593Smuzhiyun 		ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
1192*4882a593Smuzhiyun 		pbf_info = &ctdp_level->pbf_info;
1193*4882a593Smuzhiyun 		clx_n_pkg_dev.processed = 1;
1194*4882a593Smuzhiyun 		isst_ctdp_display_information(cpu, outf, tdp_level, &clx_n_pkg_dev);
1195*4882a593Smuzhiyun 		free_cpu_set(ctdp_level->core_cpumask);
1196*4882a593Smuzhiyun 		free_cpu_set(pbf_info->core_cpumask);
1197*4882a593Smuzhiyun 	}
1198*4882a593Smuzhiyun }
1199*4882a593Smuzhiyun 
dump_isst_config_for_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)1200*4882a593Smuzhiyun static void dump_isst_config_for_cpu(int cpu, void *arg1, void *arg2,
1201*4882a593Smuzhiyun 				     void *arg3, void *arg4)
1202*4882a593Smuzhiyun {
1203*4882a593Smuzhiyun 	struct isst_pkg_ctdp pkg_dev;
1204*4882a593Smuzhiyun 	int ret;
1205*4882a593Smuzhiyun 
1206*4882a593Smuzhiyun 	memset(&pkg_dev, 0, sizeof(pkg_dev));
1207*4882a593Smuzhiyun 	ret = isst_get_process_ctdp(cpu, tdp_level, &pkg_dev);
1208*4882a593Smuzhiyun 	if (ret) {
1209*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Failed to get perf-profile info on cpu", 1, cpu);
1210*4882a593Smuzhiyun 		isst_ctdp_display_information_end(outf);
1211*4882a593Smuzhiyun 		exit(1);
1212*4882a593Smuzhiyun 	} else {
1213*4882a593Smuzhiyun 		isst_ctdp_display_information(cpu, outf, tdp_level, &pkg_dev);
1214*4882a593Smuzhiyun 		isst_get_process_ctdp_complete(cpu, &pkg_dev);
1215*4882a593Smuzhiyun 	}
1216*4882a593Smuzhiyun }
1217*4882a593Smuzhiyun 
dump_isst_config(int arg)1218*4882a593Smuzhiyun static void dump_isst_config(int arg)
1219*4882a593Smuzhiyun {
1220*4882a593Smuzhiyun 	void *fn;
1221*4882a593Smuzhiyun 
1222*4882a593Smuzhiyun 	if (cmd_help) {
1223*4882a593Smuzhiyun 		fprintf(stderr,
1224*4882a593Smuzhiyun 			"Print Intel(R) Speed Select Technology Performance profile configuration\n");
1225*4882a593Smuzhiyun 		fprintf(stderr,
1226*4882a593Smuzhiyun 			"including base frequency and turbo frequency configurations\n");
1227*4882a593Smuzhiyun 		fprintf(stderr, "Optional: -l|--level : Specify tdp level\n");
1228*4882a593Smuzhiyun 		fprintf(stderr,
1229*4882a593Smuzhiyun 			"\tIf no arguments, dump information for all TDP levels\n");
1230*4882a593Smuzhiyun 		exit(0);
1231*4882a593Smuzhiyun 	}
1232*4882a593Smuzhiyun 
1233*4882a593Smuzhiyun 	if (!is_clx_n_platform())
1234*4882a593Smuzhiyun 		fn = dump_isst_config_for_cpu;
1235*4882a593Smuzhiyun 	else
1236*4882a593Smuzhiyun 		fn = dump_clx_n_config_for_cpu;
1237*4882a593Smuzhiyun 
1238*4882a593Smuzhiyun 	isst_ctdp_display_information_start(outf);
1239*4882a593Smuzhiyun 
1240*4882a593Smuzhiyun 	if (max_target_cpus)
1241*4882a593Smuzhiyun 		for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
1242*4882a593Smuzhiyun 	else
1243*4882a593Smuzhiyun 		for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
1244*4882a593Smuzhiyun 
1245*4882a593Smuzhiyun 	isst_ctdp_display_information_end(outf);
1246*4882a593Smuzhiyun }
1247*4882a593Smuzhiyun 
1248*4882a593Smuzhiyun static void adjust_scaling_max_from_base_freq(int cpu);
1249*4882a593Smuzhiyun 
set_tdp_level_for_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)1250*4882a593Smuzhiyun static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1251*4882a593Smuzhiyun 				  void *arg4)
1252*4882a593Smuzhiyun {
1253*4882a593Smuzhiyun 	int ret;
1254*4882a593Smuzhiyun 
1255*4882a593Smuzhiyun 	ret = isst_set_tdp_level(cpu, tdp_level);
1256*4882a593Smuzhiyun 	if (ret) {
1257*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Set TDP level failed", 0, 0);
1258*4882a593Smuzhiyun 		isst_ctdp_display_information_end(outf);
1259*4882a593Smuzhiyun 		exit(1);
1260*4882a593Smuzhiyun 	} else {
1261*4882a593Smuzhiyun 		isst_display_result(cpu, outf, "perf-profile", "set_tdp_level",
1262*4882a593Smuzhiyun 				    ret);
1263*4882a593Smuzhiyun 		if (force_online_offline) {
1264*4882a593Smuzhiyun 			struct isst_pkg_ctdp_level_info ctdp_level;
1265*4882a593Smuzhiyun 			int pkg_id = get_physical_package_id(cpu);
1266*4882a593Smuzhiyun 			int die_id = get_physical_die_id(cpu);
1267*4882a593Smuzhiyun 
1268*4882a593Smuzhiyun 			/* Wait for updated base frequencies */
1269*4882a593Smuzhiyun 			usleep(2000);
1270*4882a593Smuzhiyun 
1271*4882a593Smuzhiyun 			fprintf(stderr, "Option is set to online/offline\n");
1272*4882a593Smuzhiyun 			ctdp_level.core_cpumask_size =
1273*4882a593Smuzhiyun 				alloc_cpu_set(&ctdp_level.core_cpumask);
1274*4882a593Smuzhiyun 			ret = isst_get_coremask_info(cpu, tdp_level, &ctdp_level);
1275*4882a593Smuzhiyun 			if (ret) {
1276*4882a593Smuzhiyun 				isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0);
1277*4882a593Smuzhiyun 				return;
1278*4882a593Smuzhiyun 			}
1279*4882a593Smuzhiyun 			if (ctdp_level.cpu_count) {
1280*4882a593Smuzhiyun 				int i, max_cpus = get_topo_max_cpus();
1281*4882a593Smuzhiyun 				for (i = 0; i < max_cpus; ++i) {
1282*4882a593Smuzhiyun 					if (pkg_id != get_physical_package_id(i) || die_id != get_physical_die_id(i))
1283*4882a593Smuzhiyun 						continue;
1284*4882a593Smuzhiyun 					if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
1285*4882a593Smuzhiyun 						fprintf(stderr, "online cpu %d\n", i);
1286*4882a593Smuzhiyun 						set_cpu_online_offline(i, 1);
1287*4882a593Smuzhiyun 						adjust_scaling_max_from_base_freq(i);
1288*4882a593Smuzhiyun 					} else {
1289*4882a593Smuzhiyun 						fprintf(stderr, "offline cpu %d\n", i);
1290*4882a593Smuzhiyun 						set_cpu_online_offline(i, 0);
1291*4882a593Smuzhiyun 					}
1292*4882a593Smuzhiyun 				}
1293*4882a593Smuzhiyun 			}
1294*4882a593Smuzhiyun 		}
1295*4882a593Smuzhiyun 	}
1296*4882a593Smuzhiyun }
1297*4882a593Smuzhiyun 
set_tdp_level(int arg)1298*4882a593Smuzhiyun static void set_tdp_level(int arg)
1299*4882a593Smuzhiyun {
1300*4882a593Smuzhiyun 	if (cmd_help) {
1301*4882a593Smuzhiyun 		fprintf(stderr, "Set Config TDP level\n");
1302*4882a593Smuzhiyun 		fprintf(stderr,
1303*4882a593Smuzhiyun 			"\t Arguments: -l|--level : Specify tdp level\n");
1304*4882a593Smuzhiyun 		fprintf(stderr,
1305*4882a593Smuzhiyun 			"\t Optional Arguments: -o | online : online/offline for the tdp level\n");
1306*4882a593Smuzhiyun 		fprintf(stderr,
1307*4882a593Smuzhiyun 			"\t  online/offline operation has limitations, refer to Linux hotplug documentation\n");
1308*4882a593Smuzhiyun 		exit(0);
1309*4882a593Smuzhiyun 	}
1310*4882a593Smuzhiyun 
1311*4882a593Smuzhiyun 	if (tdp_level == 0xff) {
1312*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0);
1313*4882a593Smuzhiyun 		exit(1);
1314*4882a593Smuzhiyun 	}
1315*4882a593Smuzhiyun 	isst_ctdp_display_information_start(outf);
1316*4882a593Smuzhiyun 	if (max_target_cpus)
1317*4882a593Smuzhiyun 		for_each_online_target_cpu_in_set(set_tdp_level_for_cpu, NULL,
1318*4882a593Smuzhiyun 						  NULL, NULL, NULL);
1319*4882a593Smuzhiyun 	else
1320*4882a593Smuzhiyun 		for_each_online_package_in_set(set_tdp_level_for_cpu, NULL,
1321*4882a593Smuzhiyun 					       NULL, NULL, NULL);
1322*4882a593Smuzhiyun 	isst_ctdp_display_information_end(outf);
1323*4882a593Smuzhiyun }
1324*4882a593Smuzhiyun 
clx_n_dump_pbf_config_for_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)1325*4882a593Smuzhiyun static void clx_n_dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2,
1326*4882a593Smuzhiyun 				       void *arg3, void *arg4)
1327*4882a593Smuzhiyun {
1328*4882a593Smuzhiyun 	int ret;
1329*4882a593Smuzhiyun 
1330*4882a593Smuzhiyun 	ret = clx_n_config(cpu);
1331*4882a593Smuzhiyun 	if (ret) {
1332*4882a593Smuzhiyun 		isst_display_error_info_message(1, "clx_n_config failed", 0, 0);
1333*4882a593Smuzhiyun 	} else {
1334*4882a593Smuzhiyun 		struct isst_pkg_ctdp_level_info *ctdp_level;
1335*4882a593Smuzhiyun 		struct isst_pbf_info *pbf_info;
1336*4882a593Smuzhiyun 
1337*4882a593Smuzhiyun 		ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
1338*4882a593Smuzhiyun 		pbf_info = &ctdp_level->pbf_info;
1339*4882a593Smuzhiyun 		isst_pbf_display_information(cpu, outf, tdp_level, pbf_info);
1340*4882a593Smuzhiyun 		free_cpu_set(ctdp_level->core_cpumask);
1341*4882a593Smuzhiyun 		free_cpu_set(pbf_info->core_cpumask);
1342*4882a593Smuzhiyun 	}
1343*4882a593Smuzhiyun }
1344*4882a593Smuzhiyun 
dump_pbf_config_for_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)1345*4882a593Smuzhiyun static void dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1346*4882a593Smuzhiyun 				    void *arg4)
1347*4882a593Smuzhiyun {
1348*4882a593Smuzhiyun 	struct isst_pbf_info pbf_info;
1349*4882a593Smuzhiyun 	int ret;
1350*4882a593Smuzhiyun 
1351*4882a593Smuzhiyun 	ret = isst_get_pbf_info(cpu, tdp_level, &pbf_info);
1352*4882a593Smuzhiyun 	if (ret) {
1353*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Failed to get base-freq info at this level", 1, tdp_level);
1354*4882a593Smuzhiyun 		isst_ctdp_display_information_end(outf);
1355*4882a593Smuzhiyun 		exit(1);
1356*4882a593Smuzhiyun 	} else {
1357*4882a593Smuzhiyun 		isst_pbf_display_information(cpu, outf, tdp_level, &pbf_info);
1358*4882a593Smuzhiyun 		isst_get_pbf_info_complete(&pbf_info);
1359*4882a593Smuzhiyun 	}
1360*4882a593Smuzhiyun }
1361*4882a593Smuzhiyun 
dump_pbf_config(int arg)1362*4882a593Smuzhiyun static void dump_pbf_config(int arg)
1363*4882a593Smuzhiyun {
1364*4882a593Smuzhiyun 	void *fn;
1365*4882a593Smuzhiyun 
1366*4882a593Smuzhiyun 	if (cmd_help) {
1367*4882a593Smuzhiyun 		fprintf(stderr,
1368*4882a593Smuzhiyun 			"Print Intel(R) Speed Select Technology base frequency configuration for a TDP level\n");
1369*4882a593Smuzhiyun 		fprintf(stderr,
1370*4882a593Smuzhiyun 			"\tArguments: -l|--level : Specify tdp level\n");
1371*4882a593Smuzhiyun 		exit(0);
1372*4882a593Smuzhiyun 	}
1373*4882a593Smuzhiyun 
1374*4882a593Smuzhiyun 	if (tdp_level == 0xff) {
1375*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0);
1376*4882a593Smuzhiyun 		exit(1);
1377*4882a593Smuzhiyun 	}
1378*4882a593Smuzhiyun 
1379*4882a593Smuzhiyun 	if (!is_clx_n_platform())
1380*4882a593Smuzhiyun 		fn = dump_pbf_config_for_cpu;
1381*4882a593Smuzhiyun 	else
1382*4882a593Smuzhiyun 		fn = clx_n_dump_pbf_config_for_cpu;
1383*4882a593Smuzhiyun 
1384*4882a593Smuzhiyun 	isst_ctdp_display_information_start(outf);
1385*4882a593Smuzhiyun 
1386*4882a593Smuzhiyun 	if (max_target_cpus)
1387*4882a593Smuzhiyun 		for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
1388*4882a593Smuzhiyun 	else
1389*4882a593Smuzhiyun 		for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
1390*4882a593Smuzhiyun 
1391*4882a593Smuzhiyun 	isst_ctdp_display_information_end(outf);
1392*4882a593Smuzhiyun }
1393*4882a593Smuzhiyun 
set_clos_param(int cpu,int clos,int epp,int wt,int min,int max)1394*4882a593Smuzhiyun static int set_clos_param(int cpu, int clos, int epp, int wt, int min, int max)
1395*4882a593Smuzhiyun {
1396*4882a593Smuzhiyun 	struct isst_clos_config clos_config;
1397*4882a593Smuzhiyun 	int ret;
1398*4882a593Smuzhiyun 
1399*4882a593Smuzhiyun 	ret = isst_pm_get_clos(cpu, clos, &clos_config);
1400*4882a593Smuzhiyun 	if (ret) {
1401*4882a593Smuzhiyun 		isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
1402*4882a593Smuzhiyun 		return ret;
1403*4882a593Smuzhiyun 	}
1404*4882a593Smuzhiyun 	clos_config.clos_min = min;
1405*4882a593Smuzhiyun 	clos_config.clos_max = max;
1406*4882a593Smuzhiyun 	clos_config.epp = epp;
1407*4882a593Smuzhiyun 	clos_config.clos_prop_prio = wt;
1408*4882a593Smuzhiyun 	ret = isst_set_clos(cpu, clos, &clos_config);
1409*4882a593Smuzhiyun 	if (ret) {
1410*4882a593Smuzhiyun 		isst_display_error_info_message(1, "isst_set_clos failed", 0, 0);
1411*4882a593Smuzhiyun 		return ret;
1412*4882a593Smuzhiyun 	}
1413*4882a593Smuzhiyun 
1414*4882a593Smuzhiyun 	return 0;
1415*4882a593Smuzhiyun }
1416*4882a593Smuzhiyun 
set_cpufreq_scaling_min_max(int cpu,int max,int freq)1417*4882a593Smuzhiyun static int set_cpufreq_scaling_min_max(int cpu, int max, int freq)
1418*4882a593Smuzhiyun {
1419*4882a593Smuzhiyun 	char buffer[128], freq_str[16];
1420*4882a593Smuzhiyun 	int fd, ret, len;
1421*4882a593Smuzhiyun 
1422*4882a593Smuzhiyun 	if (max)
1423*4882a593Smuzhiyun 		snprintf(buffer, sizeof(buffer),
1424*4882a593Smuzhiyun 			 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
1425*4882a593Smuzhiyun 	else
1426*4882a593Smuzhiyun 		snprintf(buffer, sizeof(buffer),
1427*4882a593Smuzhiyun 			 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
1428*4882a593Smuzhiyun 
1429*4882a593Smuzhiyun 	fd = open(buffer, O_WRONLY);
1430*4882a593Smuzhiyun 	if (fd < 0)
1431*4882a593Smuzhiyun 		return fd;
1432*4882a593Smuzhiyun 
1433*4882a593Smuzhiyun 	snprintf(freq_str, sizeof(freq_str), "%d", freq);
1434*4882a593Smuzhiyun 	len = strlen(freq_str);
1435*4882a593Smuzhiyun 	ret = write(fd, freq_str, len);
1436*4882a593Smuzhiyun 	if (ret == -1) {
1437*4882a593Smuzhiyun 		close(fd);
1438*4882a593Smuzhiyun 		return ret;
1439*4882a593Smuzhiyun 	}
1440*4882a593Smuzhiyun 	close(fd);
1441*4882a593Smuzhiyun 
1442*4882a593Smuzhiyun 	return 0;
1443*4882a593Smuzhiyun }
1444*4882a593Smuzhiyun 
no_turbo(void)1445*4882a593Smuzhiyun static int no_turbo(void)
1446*4882a593Smuzhiyun {
1447*4882a593Smuzhiyun 	return parse_int_file(0, "/sys/devices/system/cpu/intel_pstate/no_turbo");
1448*4882a593Smuzhiyun }
1449*4882a593Smuzhiyun 
adjust_scaling_max_from_base_freq(int cpu)1450*4882a593Smuzhiyun static void adjust_scaling_max_from_base_freq(int cpu)
1451*4882a593Smuzhiyun {
1452*4882a593Smuzhiyun 	int base_freq, scaling_max_freq;
1453*4882a593Smuzhiyun 
1454*4882a593Smuzhiyun 	scaling_max_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
1455*4882a593Smuzhiyun 	base_freq = get_cpufreq_base_freq(cpu);
1456*4882a593Smuzhiyun 	if (scaling_max_freq < base_freq || no_turbo())
1457*4882a593Smuzhiyun 		set_cpufreq_scaling_min_max(cpu, 1, base_freq);
1458*4882a593Smuzhiyun }
1459*4882a593Smuzhiyun 
adjust_scaling_min_from_base_freq(int cpu)1460*4882a593Smuzhiyun static void adjust_scaling_min_from_base_freq(int cpu)
1461*4882a593Smuzhiyun {
1462*4882a593Smuzhiyun 	int base_freq, scaling_min_freq;
1463*4882a593Smuzhiyun 
1464*4882a593Smuzhiyun 	scaling_min_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
1465*4882a593Smuzhiyun 	base_freq = get_cpufreq_base_freq(cpu);
1466*4882a593Smuzhiyun 	if (scaling_min_freq < base_freq)
1467*4882a593Smuzhiyun 		set_cpufreq_scaling_min_max(cpu, 0, base_freq);
1468*4882a593Smuzhiyun }
1469*4882a593Smuzhiyun 
set_clx_pbf_cpufreq_scaling_min_max(int cpu)1470*4882a593Smuzhiyun static int set_clx_pbf_cpufreq_scaling_min_max(int cpu)
1471*4882a593Smuzhiyun {
1472*4882a593Smuzhiyun 	struct isst_pkg_ctdp_level_info *ctdp_level;
1473*4882a593Smuzhiyun 	struct isst_pbf_info *pbf_info;
1474*4882a593Smuzhiyun 	int i, pkg_id, die_id, freq, freq_high, freq_low;
1475*4882a593Smuzhiyun 	int ret;
1476*4882a593Smuzhiyun 
1477*4882a593Smuzhiyun 	ret = clx_n_config(cpu);
1478*4882a593Smuzhiyun 	if (ret) {
1479*4882a593Smuzhiyun 		debug_printf("cpufreq_scaling_min_max failed for CLX");
1480*4882a593Smuzhiyun 		return ret;
1481*4882a593Smuzhiyun 	}
1482*4882a593Smuzhiyun 
1483*4882a593Smuzhiyun 	ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
1484*4882a593Smuzhiyun 	pbf_info = &ctdp_level->pbf_info;
1485*4882a593Smuzhiyun 	freq_high = pbf_info->p1_high * 100000;
1486*4882a593Smuzhiyun 	freq_low = pbf_info->p1_low * 100000;
1487*4882a593Smuzhiyun 
1488*4882a593Smuzhiyun 	pkg_id = get_physical_package_id(cpu);
1489*4882a593Smuzhiyun 	die_id = get_physical_die_id(cpu);
1490*4882a593Smuzhiyun 	for (i = 0; i < get_topo_max_cpus(); ++i) {
1491*4882a593Smuzhiyun 		if (pkg_id != get_physical_package_id(i) ||
1492*4882a593Smuzhiyun 		    die_id != get_physical_die_id(i))
1493*4882a593Smuzhiyun 			continue;
1494*4882a593Smuzhiyun 
1495*4882a593Smuzhiyun 		if (CPU_ISSET_S(i, pbf_info->core_cpumask_size,
1496*4882a593Smuzhiyun 				  pbf_info->core_cpumask))
1497*4882a593Smuzhiyun 			freq = freq_high;
1498*4882a593Smuzhiyun 		else
1499*4882a593Smuzhiyun 			freq = freq_low;
1500*4882a593Smuzhiyun 
1501*4882a593Smuzhiyun 		set_cpufreq_scaling_min_max(i, 1, freq);
1502*4882a593Smuzhiyun 		set_cpufreq_scaling_min_max(i, 0, freq);
1503*4882a593Smuzhiyun 	}
1504*4882a593Smuzhiyun 
1505*4882a593Smuzhiyun 	return 0;
1506*4882a593Smuzhiyun }
1507*4882a593Smuzhiyun 
set_cpufreq_scaling_min_max_from_cpuinfo(int cpu,int cpuinfo_max,int scaling_max)1508*4882a593Smuzhiyun static int set_cpufreq_scaling_min_max_from_cpuinfo(int cpu, int cpuinfo_max, int scaling_max)
1509*4882a593Smuzhiyun {
1510*4882a593Smuzhiyun 	char buffer[128], min_freq[16];
1511*4882a593Smuzhiyun 	int fd, ret, len;
1512*4882a593Smuzhiyun 
1513*4882a593Smuzhiyun 	if (!CPU_ISSET_S(cpu, present_cpumask_size, present_cpumask))
1514*4882a593Smuzhiyun 		return -1;
1515*4882a593Smuzhiyun 
1516*4882a593Smuzhiyun 	if (cpuinfo_max)
1517*4882a593Smuzhiyun 		snprintf(buffer, sizeof(buffer),
1518*4882a593Smuzhiyun 			 "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpu);
1519*4882a593Smuzhiyun 	else
1520*4882a593Smuzhiyun 		snprintf(buffer, sizeof(buffer),
1521*4882a593Smuzhiyun 			 "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_min_freq", cpu);
1522*4882a593Smuzhiyun 
1523*4882a593Smuzhiyun 	fd = open(buffer, O_RDONLY);
1524*4882a593Smuzhiyun 	if (fd < 0)
1525*4882a593Smuzhiyun 		return fd;
1526*4882a593Smuzhiyun 
1527*4882a593Smuzhiyun 	len = read(fd, min_freq, sizeof(min_freq));
1528*4882a593Smuzhiyun 	close(fd);
1529*4882a593Smuzhiyun 
1530*4882a593Smuzhiyun 	if (len < 0)
1531*4882a593Smuzhiyun 		return len;
1532*4882a593Smuzhiyun 
1533*4882a593Smuzhiyun 	if (scaling_max)
1534*4882a593Smuzhiyun 		snprintf(buffer, sizeof(buffer),
1535*4882a593Smuzhiyun 			 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
1536*4882a593Smuzhiyun 	else
1537*4882a593Smuzhiyun 		snprintf(buffer, sizeof(buffer),
1538*4882a593Smuzhiyun 			 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
1539*4882a593Smuzhiyun 
1540*4882a593Smuzhiyun 	fd = open(buffer, O_WRONLY);
1541*4882a593Smuzhiyun 	if (fd < 0)
1542*4882a593Smuzhiyun 		return fd;
1543*4882a593Smuzhiyun 
1544*4882a593Smuzhiyun 	len = strlen(min_freq);
1545*4882a593Smuzhiyun 	ret = write(fd, min_freq, len);
1546*4882a593Smuzhiyun 	if (ret == -1) {
1547*4882a593Smuzhiyun 		close(fd);
1548*4882a593Smuzhiyun 		return ret;
1549*4882a593Smuzhiyun 	}
1550*4882a593Smuzhiyun 	close(fd);
1551*4882a593Smuzhiyun 
1552*4882a593Smuzhiyun 	return 0;
1553*4882a593Smuzhiyun }
1554*4882a593Smuzhiyun 
set_scaling_min_to_cpuinfo_max(int cpu)1555*4882a593Smuzhiyun static void set_scaling_min_to_cpuinfo_max(int cpu)
1556*4882a593Smuzhiyun {
1557*4882a593Smuzhiyun 	int i, pkg_id, die_id;
1558*4882a593Smuzhiyun 
1559*4882a593Smuzhiyun 	pkg_id = get_physical_package_id(cpu);
1560*4882a593Smuzhiyun 	die_id = get_physical_die_id(cpu);
1561*4882a593Smuzhiyun 	for (i = 0; i < get_topo_max_cpus(); ++i) {
1562*4882a593Smuzhiyun 		if (pkg_id != get_physical_package_id(i) ||
1563*4882a593Smuzhiyun 		    die_id != get_physical_die_id(i))
1564*4882a593Smuzhiyun 			continue;
1565*4882a593Smuzhiyun 
1566*4882a593Smuzhiyun 		set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 0);
1567*4882a593Smuzhiyun 		adjust_scaling_min_from_base_freq(i);
1568*4882a593Smuzhiyun 	}
1569*4882a593Smuzhiyun }
1570*4882a593Smuzhiyun 
set_scaling_min_to_cpuinfo_min(int cpu)1571*4882a593Smuzhiyun static void set_scaling_min_to_cpuinfo_min(int cpu)
1572*4882a593Smuzhiyun {
1573*4882a593Smuzhiyun 	int i, pkg_id, die_id;
1574*4882a593Smuzhiyun 
1575*4882a593Smuzhiyun 	pkg_id = get_physical_package_id(cpu);
1576*4882a593Smuzhiyun 	die_id = get_physical_die_id(cpu);
1577*4882a593Smuzhiyun 	for (i = 0; i < get_topo_max_cpus(); ++i) {
1578*4882a593Smuzhiyun 		if (pkg_id != get_physical_package_id(i) ||
1579*4882a593Smuzhiyun 		    die_id != get_physical_die_id(i))
1580*4882a593Smuzhiyun 			continue;
1581*4882a593Smuzhiyun 
1582*4882a593Smuzhiyun 		set_cpufreq_scaling_min_max_from_cpuinfo(i, 0, 0);
1583*4882a593Smuzhiyun 	}
1584*4882a593Smuzhiyun }
1585*4882a593Smuzhiyun 
set_scaling_max_to_cpuinfo_max(int cpu)1586*4882a593Smuzhiyun static void set_scaling_max_to_cpuinfo_max(int cpu)
1587*4882a593Smuzhiyun {
1588*4882a593Smuzhiyun 	int i, pkg_id, die_id;
1589*4882a593Smuzhiyun 
1590*4882a593Smuzhiyun 	pkg_id = get_physical_package_id(cpu);
1591*4882a593Smuzhiyun 	die_id = get_physical_die_id(cpu);
1592*4882a593Smuzhiyun 	for (i = 0; i < get_topo_max_cpus(); ++i) {
1593*4882a593Smuzhiyun 		if (pkg_id != get_physical_package_id(i) ||
1594*4882a593Smuzhiyun 		    die_id != get_physical_die_id(i))
1595*4882a593Smuzhiyun 			continue;
1596*4882a593Smuzhiyun 
1597*4882a593Smuzhiyun 		set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 1);
1598*4882a593Smuzhiyun 	}
1599*4882a593Smuzhiyun }
1600*4882a593Smuzhiyun 
set_core_priority_and_min(int cpu,int mask_size,cpu_set_t * cpu_mask,int min_high,int min_low)1601*4882a593Smuzhiyun static int set_core_priority_and_min(int cpu, int mask_size,
1602*4882a593Smuzhiyun 				     cpu_set_t *cpu_mask, int min_high,
1603*4882a593Smuzhiyun 				     int min_low)
1604*4882a593Smuzhiyun {
1605*4882a593Smuzhiyun 	int pkg_id, die_id, ret, i;
1606*4882a593Smuzhiyun 
1607*4882a593Smuzhiyun 	if (!CPU_COUNT_S(mask_size, cpu_mask))
1608*4882a593Smuzhiyun 		return -1;
1609*4882a593Smuzhiyun 
1610*4882a593Smuzhiyun 	ret = set_clos_param(cpu, 0, 0, 0, min_high, 0xff);
1611*4882a593Smuzhiyun 	if (ret)
1612*4882a593Smuzhiyun 		return ret;
1613*4882a593Smuzhiyun 
1614*4882a593Smuzhiyun 	ret = set_clos_param(cpu, 1, 15, 15, min_low, 0xff);
1615*4882a593Smuzhiyun 	if (ret)
1616*4882a593Smuzhiyun 		return ret;
1617*4882a593Smuzhiyun 
1618*4882a593Smuzhiyun 	ret = set_clos_param(cpu, 2, 15, 15, min_low, 0xff);
1619*4882a593Smuzhiyun 	if (ret)
1620*4882a593Smuzhiyun 		return ret;
1621*4882a593Smuzhiyun 
1622*4882a593Smuzhiyun 	ret = set_clos_param(cpu, 3, 15, 15, min_low, 0xff);
1623*4882a593Smuzhiyun 	if (ret)
1624*4882a593Smuzhiyun 		return ret;
1625*4882a593Smuzhiyun 
1626*4882a593Smuzhiyun 	pkg_id = get_physical_package_id(cpu);
1627*4882a593Smuzhiyun 	die_id = get_physical_die_id(cpu);
1628*4882a593Smuzhiyun 	for (i = 0; i < get_topo_max_cpus(); ++i) {
1629*4882a593Smuzhiyun 		int clos;
1630*4882a593Smuzhiyun 
1631*4882a593Smuzhiyun 		if (pkg_id != get_physical_package_id(i) ||
1632*4882a593Smuzhiyun 		    die_id != get_physical_die_id(i))
1633*4882a593Smuzhiyun 			continue;
1634*4882a593Smuzhiyun 
1635*4882a593Smuzhiyun 		if (CPU_ISSET_S(i, mask_size, cpu_mask))
1636*4882a593Smuzhiyun 			clos = 0;
1637*4882a593Smuzhiyun 		else
1638*4882a593Smuzhiyun 			clos = 3;
1639*4882a593Smuzhiyun 
1640*4882a593Smuzhiyun 		debug_printf("Associate cpu: %d clos: %d\n", i, clos);
1641*4882a593Smuzhiyun 		ret = isst_clos_associate(i, clos);
1642*4882a593Smuzhiyun 		if (ret) {
1643*4882a593Smuzhiyun 			isst_display_error_info_message(1, "isst_clos_associate failed", 0, 0);
1644*4882a593Smuzhiyun 			return ret;
1645*4882a593Smuzhiyun 		}
1646*4882a593Smuzhiyun 	}
1647*4882a593Smuzhiyun 
1648*4882a593Smuzhiyun 	return 0;
1649*4882a593Smuzhiyun }
1650*4882a593Smuzhiyun 
set_pbf_core_power(int cpu)1651*4882a593Smuzhiyun static int set_pbf_core_power(int cpu)
1652*4882a593Smuzhiyun {
1653*4882a593Smuzhiyun 	struct isst_pbf_info pbf_info;
1654*4882a593Smuzhiyun 	struct isst_pkg_ctdp pkg_dev;
1655*4882a593Smuzhiyun 	int ret;
1656*4882a593Smuzhiyun 
1657*4882a593Smuzhiyun 	ret = isst_get_ctdp_levels(cpu, &pkg_dev);
1658*4882a593Smuzhiyun 	if (ret) {
1659*4882a593Smuzhiyun 		debug_printf("isst_get_ctdp_levels failed");
1660*4882a593Smuzhiyun 		return ret;
1661*4882a593Smuzhiyun 	}
1662*4882a593Smuzhiyun 	debug_printf("Current_level: %d\n", pkg_dev.current_level);
1663*4882a593Smuzhiyun 
1664*4882a593Smuzhiyun 	ret = isst_get_pbf_info(cpu, pkg_dev.current_level, &pbf_info);
1665*4882a593Smuzhiyun 	if (ret) {
1666*4882a593Smuzhiyun 		debug_printf("isst_get_pbf_info failed");
1667*4882a593Smuzhiyun 		return ret;
1668*4882a593Smuzhiyun 	}
1669*4882a593Smuzhiyun 	debug_printf("p1_high: %d p1_low: %d\n", pbf_info.p1_high,
1670*4882a593Smuzhiyun 		     pbf_info.p1_low);
1671*4882a593Smuzhiyun 
1672*4882a593Smuzhiyun 	ret = set_core_priority_and_min(cpu, pbf_info.core_cpumask_size,
1673*4882a593Smuzhiyun 					pbf_info.core_cpumask,
1674*4882a593Smuzhiyun 					pbf_info.p1_high, pbf_info.p1_low);
1675*4882a593Smuzhiyun 	if (ret) {
1676*4882a593Smuzhiyun 		debug_printf("set_core_priority_and_min failed");
1677*4882a593Smuzhiyun 		return ret;
1678*4882a593Smuzhiyun 	}
1679*4882a593Smuzhiyun 
1680*4882a593Smuzhiyun 	ret = isst_pm_qos_config(cpu, 1, 1);
1681*4882a593Smuzhiyun 	if (ret) {
1682*4882a593Smuzhiyun 		debug_printf("isst_pm_qos_config failed");
1683*4882a593Smuzhiyun 		return ret;
1684*4882a593Smuzhiyun 	}
1685*4882a593Smuzhiyun 
1686*4882a593Smuzhiyun 	return 0;
1687*4882a593Smuzhiyun }
1688*4882a593Smuzhiyun 
set_pbf_for_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)1689*4882a593Smuzhiyun static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1690*4882a593Smuzhiyun 			    void *arg4)
1691*4882a593Smuzhiyun {
1692*4882a593Smuzhiyun 	struct isst_pkg_ctdp_level_info ctdp_level;
1693*4882a593Smuzhiyun 	struct isst_pkg_ctdp pkg_dev;
1694*4882a593Smuzhiyun 	int ret;
1695*4882a593Smuzhiyun 	int status = *(int *)arg4;
1696*4882a593Smuzhiyun 
1697*4882a593Smuzhiyun 	if (is_clx_n_platform()) {
1698*4882a593Smuzhiyun 		ret = 0;
1699*4882a593Smuzhiyun 		if (status) {
1700*4882a593Smuzhiyun 			set_clx_pbf_cpufreq_scaling_min_max(cpu);
1701*4882a593Smuzhiyun 
1702*4882a593Smuzhiyun 		} else {
1703*4882a593Smuzhiyun 			set_scaling_max_to_cpuinfo_max(cpu);
1704*4882a593Smuzhiyun 			set_scaling_min_to_cpuinfo_min(cpu);
1705*4882a593Smuzhiyun 		}
1706*4882a593Smuzhiyun 		goto disp_result;
1707*4882a593Smuzhiyun 	}
1708*4882a593Smuzhiyun 
1709*4882a593Smuzhiyun 	ret = isst_get_ctdp_levels(cpu, &pkg_dev);
1710*4882a593Smuzhiyun 	if (ret) {
1711*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
1712*4882a593Smuzhiyun 		goto disp_result;
1713*4882a593Smuzhiyun 	}
1714*4882a593Smuzhiyun 
1715*4882a593Smuzhiyun 	ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level);
1716*4882a593Smuzhiyun 	if (ret) {
1717*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Failed to get current level", 0, 0);
1718*4882a593Smuzhiyun 		goto disp_result;
1719*4882a593Smuzhiyun 	}
1720*4882a593Smuzhiyun 
1721*4882a593Smuzhiyun 	if (!ctdp_level.pbf_support) {
1722*4882a593Smuzhiyun 		isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, pkg_dev.current_level);
1723*4882a593Smuzhiyun 		ret = -1;
1724*4882a593Smuzhiyun 		goto disp_result;
1725*4882a593Smuzhiyun 	}
1726*4882a593Smuzhiyun 
1727*4882a593Smuzhiyun 	if (auto_mode && status) {
1728*4882a593Smuzhiyun 		ret = set_pbf_core_power(cpu);
1729*4882a593Smuzhiyun 		if (ret)
1730*4882a593Smuzhiyun 			goto disp_result;
1731*4882a593Smuzhiyun 	}
1732*4882a593Smuzhiyun 
1733*4882a593Smuzhiyun 	ret = isst_set_pbf_fact_status(cpu, 1, status);
1734*4882a593Smuzhiyun 	if (ret) {
1735*4882a593Smuzhiyun 		debug_printf("isst_set_pbf_fact_status failed");
1736*4882a593Smuzhiyun 		if (auto_mode)
1737*4882a593Smuzhiyun 			isst_pm_qos_config(cpu, 0, 0);
1738*4882a593Smuzhiyun 	} else {
1739*4882a593Smuzhiyun 		if (auto_mode) {
1740*4882a593Smuzhiyun 			if (status)
1741*4882a593Smuzhiyun 				set_scaling_min_to_cpuinfo_max(cpu);
1742*4882a593Smuzhiyun 			else
1743*4882a593Smuzhiyun 				set_scaling_min_to_cpuinfo_min(cpu);
1744*4882a593Smuzhiyun 		}
1745*4882a593Smuzhiyun 	}
1746*4882a593Smuzhiyun 
1747*4882a593Smuzhiyun 	if (auto_mode && !status)
1748*4882a593Smuzhiyun 		isst_pm_qos_config(cpu, 0, 1);
1749*4882a593Smuzhiyun 
1750*4882a593Smuzhiyun disp_result:
1751*4882a593Smuzhiyun 	if (status)
1752*4882a593Smuzhiyun 		isst_display_result(cpu, outf, "base-freq", "enable",
1753*4882a593Smuzhiyun 				    ret);
1754*4882a593Smuzhiyun 	else
1755*4882a593Smuzhiyun 		isst_display_result(cpu, outf, "base-freq", "disable",
1756*4882a593Smuzhiyun 				    ret);
1757*4882a593Smuzhiyun }
1758*4882a593Smuzhiyun 
set_pbf_enable(int arg)1759*4882a593Smuzhiyun static void set_pbf_enable(int arg)
1760*4882a593Smuzhiyun {
1761*4882a593Smuzhiyun 	int enable = arg;
1762*4882a593Smuzhiyun 
1763*4882a593Smuzhiyun 	if (cmd_help) {
1764*4882a593Smuzhiyun 		if (enable) {
1765*4882a593Smuzhiyun 			fprintf(stderr,
1766*4882a593Smuzhiyun 				"Enable Intel Speed Select Technology base frequency feature\n");
1767*4882a593Smuzhiyun 			if (is_clx_n_platform()) {
1768*4882a593Smuzhiyun 				fprintf(stderr,
1769*4882a593Smuzhiyun 					"\tOn this platform this command doesn't enable feature in the hardware.\n");
1770*4882a593Smuzhiyun 				fprintf(stderr,
1771*4882a593Smuzhiyun 					"\tIt updates the cpufreq scaling_min_freq to match cpufreq base_frequency.\n");
1772*4882a593Smuzhiyun 				exit(0);
1773*4882a593Smuzhiyun 
1774*4882a593Smuzhiyun 			}
1775*4882a593Smuzhiyun 			fprintf(stderr,
1776*4882a593Smuzhiyun 				"\tOptional Arguments: -a|--auto : Use priority of cores to set core-power associations\n");
1777*4882a593Smuzhiyun 		} else {
1778*4882a593Smuzhiyun 
1779*4882a593Smuzhiyun 			if (is_clx_n_platform()) {
1780*4882a593Smuzhiyun 				fprintf(stderr,
1781*4882a593Smuzhiyun 					"\tOn this platform this command doesn't disable feature in the hardware.\n");
1782*4882a593Smuzhiyun 				fprintf(stderr,
1783*4882a593Smuzhiyun 					"\tIt updates the cpufreq scaling_min_freq to match cpuinfo_min_freq\n");
1784*4882a593Smuzhiyun 				exit(0);
1785*4882a593Smuzhiyun 			}
1786*4882a593Smuzhiyun 			fprintf(stderr,
1787*4882a593Smuzhiyun 				"Disable Intel Speed Select Technology base frequency feature\n");
1788*4882a593Smuzhiyun 			fprintf(stderr,
1789*4882a593Smuzhiyun 				"\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
1790*4882a593Smuzhiyun 		}
1791*4882a593Smuzhiyun 		exit(0);
1792*4882a593Smuzhiyun 	}
1793*4882a593Smuzhiyun 
1794*4882a593Smuzhiyun 	isst_ctdp_display_information_start(outf);
1795*4882a593Smuzhiyun 	if (max_target_cpus)
1796*4882a593Smuzhiyun 		for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
1797*4882a593Smuzhiyun 						  NULL, &enable);
1798*4882a593Smuzhiyun 	else
1799*4882a593Smuzhiyun 		for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
1800*4882a593Smuzhiyun 					       NULL, &enable);
1801*4882a593Smuzhiyun 	isst_ctdp_display_information_end(outf);
1802*4882a593Smuzhiyun }
1803*4882a593Smuzhiyun 
dump_fact_config_for_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)1804*4882a593Smuzhiyun static void dump_fact_config_for_cpu(int cpu, void *arg1, void *arg2,
1805*4882a593Smuzhiyun 				     void *arg3, void *arg4)
1806*4882a593Smuzhiyun {
1807*4882a593Smuzhiyun 	struct isst_fact_info fact_info;
1808*4882a593Smuzhiyun 	int ret;
1809*4882a593Smuzhiyun 
1810*4882a593Smuzhiyun 	ret = isst_get_fact_info(cpu, tdp_level, fact_bucket, &fact_info);
1811*4882a593Smuzhiyun 	if (ret) {
1812*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Failed to get turbo-freq info at this level", 1, tdp_level);
1813*4882a593Smuzhiyun 		isst_ctdp_display_information_end(outf);
1814*4882a593Smuzhiyun 		exit(1);
1815*4882a593Smuzhiyun 	} else {
1816*4882a593Smuzhiyun 		isst_fact_display_information(cpu, outf, tdp_level, fact_bucket,
1817*4882a593Smuzhiyun 					      fact_avx, &fact_info);
1818*4882a593Smuzhiyun 	}
1819*4882a593Smuzhiyun }
1820*4882a593Smuzhiyun 
dump_fact_config(int arg)1821*4882a593Smuzhiyun static void dump_fact_config(int arg)
1822*4882a593Smuzhiyun {
1823*4882a593Smuzhiyun 	if (cmd_help) {
1824*4882a593Smuzhiyun 		fprintf(stderr,
1825*4882a593Smuzhiyun 			"Print complete Intel Speed Select Technology turbo frequency configuration for a TDP level. Other arguments are optional.\n");
1826*4882a593Smuzhiyun 		fprintf(stderr,
1827*4882a593Smuzhiyun 			"\tArguments: -l|--level : Specify tdp level\n");
1828*4882a593Smuzhiyun 		fprintf(stderr,
1829*4882a593Smuzhiyun 			"\tArguments: -b|--bucket : Bucket index to dump\n");
1830*4882a593Smuzhiyun 		fprintf(stderr,
1831*4882a593Smuzhiyun 			"\tArguments: -r|--trl-type : Specify trl type: sse|avx2|avx512\n");
1832*4882a593Smuzhiyun 		exit(0);
1833*4882a593Smuzhiyun 	}
1834*4882a593Smuzhiyun 
1835*4882a593Smuzhiyun 	if (tdp_level == 0xff) {
1836*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Invalid command: specify tdp_level\n", 0, 0);
1837*4882a593Smuzhiyun 		exit(1);
1838*4882a593Smuzhiyun 	}
1839*4882a593Smuzhiyun 
1840*4882a593Smuzhiyun 	isst_ctdp_display_information_start(outf);
1841*4882a593Smuzhiyun 	if (max_target_cpus)
1842*4882a593Smuzhiyun 		for_each_online_target_cpu_in_set(dump_fact_config_for_cpu,
1843*4882a593Smuzhiyun 						  NULL, NULL, NULL, NULL);
1844*4882a593Smuzhiyun 	else
1845*4882a593Smuzhiyun 		for_each_online_package_in_set(dump_fact_config_for_cpu, NULL,
1846*4882a593Smuzhiyun 					       NULL, NULL, NULL);
1847*4882a593Smuzhiyun 	isst_ctdp_display_information_end(outf);
1848*4882a593Smuzhiyun }
1849*4882a593Smuzhiyun 
set_fact_for_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)1850*4882a593Smuzhiyun static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1851*4882a593Smuzhiyun 			     void *arg4)
1852*4882a593Smuzhiyun {
1853*4882a593Smuzhiyun 	struct isst_pkg_ctdp_level_info ctdp_level;
1854*4882a593Smuzhiyun 	struct isst_pkg_ctdp pkg_dev;
1855*4882a593Smuzhiyun 	int ret;
1856*4882a593Smuzhiyun 	int status = *(int *)arg4;
1857*4882a593Smuzhiyun 
1858*4882a593Smuzhiyun 	ret = isst_get_ctdp_levels(cpu, &pkg_dev);
1859*4882a593Smuzhiyun 	if (ret) {
1860*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
1861*4882a593Smuzhiyun 		goto disp_results;
1862*4882a593Smuzhiyun 	}
1863*4882a593Smuzhiyun 
1864*4882a593Smuzhiyun 	ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level);
1865*4882a593Smuzhiyun 	if (ret) {
1866*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Failed to get current level", 0, 0);
1867*4882a593Smuzhiyun 		goto disp_results;
1868*4882a593Smuzhiyun 	}
1869*4882a593Smuzhiyun 
1870*4882a593Smuzhiyun 	if (!ctdp_level.fact_support) {
1871*4882a593Smuzhiyun 		isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, pkg_dev.current_level);
1872*4882a593Smuzhiyun 		ret = -1;
1873*4882a593Smuzhiyun 		goto disp_results;
1874*4882a593Smuzhiyun 	}
1875*4882a593Smuzhiyun 
1876*4882a593Smuzhiyun 	if (status) {
1877*4882a593Smuzhiyun 		ret = isst_pm_qos_config(cpu, 1, 1);
1878*4882a593Smuzhiyun 		if (ret)
1879*4882a593Smuzhiyun 			goto disp_results;
1880*4882a593Smuzhiyun 	}
1881*4882a593Smuzhiyun 
1882*4882a593Smuzhiyun 	ret = isst_set_pbf_fact_status(cpu, 0, status);
1883*4882a593Smuzhiyun 	if (ret) {
1884*4882a593Smuzhiyun 		debug_printf("isst_set_pbf_fact_status failed");
1885*4882a593Smuzhiyun 		if (auto_mode)
1886*4882a593Smuzhiyun 			isst_pm_qos_config(cpu, 0, 0);
1887*4882a593Smuzhiyun 
1888*4882a593Smuzhiyun 		goto disp_results;
1889*4882a593Smuzhiyun 	}
1890*4882a593Smuzhiyun 
1891*4882a593Smuzhiyun 	/* Set TRL */
1892*4882a593Smuzhiyun 	if (status) {
1893*4882a593Smuzhiyun 		struct isst_pkg_ctdp pkg_dev;
1894*4882a593Smuzhiyun 
1895*4882a593Smuzhiyun 		ret = isst_get_ctdp_levels(cpu, &pkg_dev);
1896*4882a593Smuzhiyun 		if (!ret)
1897*4882a593Smuzhiyun 			ret = isst_set_trl(cpu, fact_trl);
1898*4882a593Smuzhiyun 		if (ret && auto_mode)
1899*4882a593Smuzhiyun 			isst_pm_qos_config(cpu, 0, 0);
1900*4882a593Smuzhiyun 	} else {
1901*4882a593Smuzhiyun 		if (auto_mode)
1902*4882a593Smuzhiyun 			isst_pm_qos_config(cpu, 0, 0);
1903*4882a593Smuzhiyun 	}
1904*4882a593Smuzhiyun 
1905*4882a593Smuzhiyun disp_results:
1906*4882a593Smuzhiyun 	if (status) {
1907*4882a593Smuzhiyun 		isst_display_result(cpu, outf, "turbo-freq", "enable", ret);
1908*4882a593Smuzhiyun 		if (ret)
1909*4882a593Smuzhiyun 			fact_enable_fail = ret;
1910*4882a593Smuzhiyun 	} else {
1911*4882a593Smuzhiyun 		/* Since we modified TRL during Fact enable, restore it */
1912*4882a593Smuzhiyun 		isst_set_trl_from_current_tdp(cpu, fact_trl);
1913*4882a593Smuzhiyun 		isst_display_result(cpu, outf, "turbo-freq", "disable", ret);
1914*4882a593Smuzhiyun 	}
1915*4882a593Smuzhiyun }
1916*4882a593Smuzhiyun 
set_fact_enable(int arg)1917*4882a593Smuzhiyun static void set_fact_enable(int arg)
1918*4882a593Smuzhiyun {
1919*4882a593Smuzhiyun 	int i, ret, enable = arg;
1920*4882a593Smuzhiyun 
1921*4882a593Smuzhiyun 	if (cmd_help) {
1922*4882a593Smuzhiyun 		if (enable) {
1923*4882a593Smuzhiyun 			fprintf(stderr,
1924*4882a593Smuzhiyun 				"Enable Intel Speed Select Technology Turbo frequency feature\n");
1925*4882a593Smuzhiyun 			fprintf(stderr,
1926*4882a593Smuzhiyun 				"Optional: -t|--trl : Specify turbo ratio limit\n");
1927*4882a593Smuzhiyun 			fprintf(stderr,
1928*4882a593Smuzhiyun 				"\tOptional Arguments: -a|--auto : Designate specified target CPUs with");
1929*4882a593Smuzhiyun 			fprintf(stderr,
1930*4882a593Smuzhiyun 				"-C|--cpu option as as high priority using core-power feature\n");
1931*4882a593Smuzhiyun 		} else {
1932*4882a593Smuzhiyun 			fprintf(stderr,
1933*4882a593Smuzhiyun 				"Disable Intel Speed Select Technology turbo frequency feature\n");
1934*4882a593Smuzhiyun 			fprintf(stderr,
1935*4882a593Smuzhiyun 				"Optional: -t|--trl : Specify turbo ratio limit\n");
1936*4882a593Smuzhiyun 			fprintf(stderr,
1937*4882a593Smuzhiyun 				"\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
1938*4882a593Smuzhiyun 		}
1939*4882a593Smuzhiyun 		exit(0);
1940*4882a593Smuzhiyun 	}
1941*4882a593Smuzhiyun 
1942*4882a593Smuzhiyun 	isst_ctdp_display_information_start(outf);
1943*4882a593Smuzhiyun 	if (max_target_cpus)
1944*4882a593Smuzhiyun 		for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
1945*4882a593Smuzhiyun 						  NULL, &enable);
1946*4882a593Smuzhiyun 	else
1947*4882a593Smuzhiyun 		for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
1948*4882a593Smuzhiyun 					       NULL, &enable);
1949*4882a593Smuzhiyun 	isst_ctdp_display_information_end(outf);
1950*4882a593Smuzhiyun 
1951*4882a593Smuzhiyun 	if (!fact_enable_fail && enable && auto_mode) {
1952*4882a593Smuzhiyun 		/*
1953*4882a593Smuzhiyun 		 * When we adjust CLOS param, we have to set for siblings also.
1954*4882a593Smuzhiyun 		 * So for the each user specified CPU, also add the sibling
1955*4882a593Smuzhiyun 		 * in the present_cpu_mask.
1956*4882a593Smuzhiyun 		 */
1957*4882a593Smuzhiyun 		for (i = 0; i < get_topo_max_cpus(); ++i) {
1958*4882a593Smuzhiyun 			char buffer[128], sibling_list[128], *cpu_str;
1959*4882a593Smuzhiyun 			int fd, len;
1960*4882a593Smuzhiyun 
1961*4882a593Smuzhiyun 			if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
1962*4882a593Smuzhiyun 				continue;
1963*4882a593Smuzhiyun 
1964*4882a593Smuzhiyun 			snprintf(buffer, sizeof(buffer),
1965*4882a593Smuzhiyun 				 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", i);
1966*4882a593Smuzhiyun 
1967*4882a593Smuzhiyun 			fd = open(buffer, O_RDONLY);
1968*4882a593Smuzhiyun 			if (fd < 0)
1969*4882a593Smuzhiyun 				continue;
1970*4882a593Smuzhiyun 
1971*4882a593Smuzhiyun 			len = read(fd, sibling_list, sizeof(sibling_list));
1972*4882a593Smuzhiyun 			close(fd);
1973*4882a593Smuzhiyun 
1974*4882a593Smuzhiyun 			if (len < 0)
1975*4882a593Smuzhiyun 				continue;
1976*4882a593Smuzhiyun 
1977*4882a593Smuzhiyun 			cpu_str = strtok(sibling_list, ",");
1978*4882a593Smuzhiyun 			while (cpu_str != NULL) {
1979*4882a593Smuzhiyun 				int cpu;
1980*4882a593Smuzhiyun 
1981*4882a593Smuzhiyun 				sscanf(cpu_str, "%d", &cpu);
1982*4882a593Smuzhiyun 				CPU_SET_S(cpu, target_cpumask_size, target_cpumask);
1983*4882a593Smuzhiyun 				cpu_str = strtok(NULL, ",");
1984*4882a593Smuzhiyun 			}
1985*4882a593Smuzhiyun 		}
1986*4882a593Smuzhiyun 
1987*4882a593Smuzhiyun 		for (i = 0; i < get_topo_max_cpus(); ++i) {
1988*4882a593Smuzhiyun 			int clos;
1989*4882a593Smuzhiyun 
1990*4882a593Smuzhiyun 			if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
1991*4882a593Smuzhiyun 				continue;
1992*4882a593Smuzhiyun 
1993*4882a593Smuzhiyun 			ret = set_clos_param(i, 0, 0, 0, 0, 0xff);
1994*4882a593Smuzhiyun 			if (ret)
1995*4882a593Smuzhiyun 				goto error_disp;
1996*4882a593Smuzhiyun 
1997*4882a593Smuzhiyun 			ret = set_clos_param(i, 1, 15, 15, 0, 0xff);
1998*4882a593Smuzhiyun 			if (ret)
1999*4882a593Smuzhiyun 				goto error_disp;
2000*4882a593Smuzhiyun 
2001*4882a593Smuzhiyun 			ret = set_clos_param(i, 2, 15, 15, 0, 0xff);
2002*4882a593Smuzhiyun 			if (ret)
2003*4882a593Smuzhiyun 				goto error_disp;
2004*4882a593Smuzhiyun 
2005*4882a593Smuzhiyun 			ret = set_clos_param(i, 3, 15, 15, 0, 0xff);
2006*4882a593Smuzhiyun 			if (ret)
2007*4882a593Smuzhiyun 				goto error_disp;
2008*4882a593Smuzhiyun 
2009*4882a593Smuzhiyun 			if (CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
2010*4882a593Smuzhiyun 				clos = 0;
2011*4882a593Smuzhiyun 			else
2012*4882a593Smuzhiyun 				clos = 3;
2013*4882a593Smuzhiyun 
2014*4882a593Smuzhiyun 			debug_printf("Associate cpu: %d clos: %d\n", i, clos);
2015*4882a593Smuzhiyun 			ret = isst_clos_associate(i, clos);
2016*4882a593Smuzhiyun 			if (ret)
2017*4882a593Smuzhiyun 				goto error_disp;
2018*4882a593Smuzhiyun 		}
2019*4882a593Smuzhiyun 		isst_display_result(-1, outf, "turbo-freq --auto", "enable", 0);
2020*4882a593Smuzhiyun 	}
2021*4882a593Smuzhiyun 
2022*4882a593Smuzhiyun 	return;
2023*4882a593Smuzhiyun 
2024*4882a593Smuzhiyun error_disp:
2025*4882a593Smuzhiyun 	isst_display_result(i, outf, "turbo-freq --auto", "enable", ret);
2026*4882a593Smuzhiyun 
2027*4882a593Smuzhiyun }
2028*4882a593Smuzhiyun 
enable_clos_qos_config(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)2029*4882a593Smuzhiyun static void enable_clos_qos_config(int cpu, void *arg1, void *arg2, void *arg3,
2030*4882a593Smuzhiyun 				   void *arg4)
2031*4882a593Smuzhiyun {
2032*4882a593Smuzhiyun 	int ret;
2033*4882a593Smuzhiyun 	int status = *(int *)arg4;
2034*4882a593Smuzhiyun 
2035*4882a593Smuzhiyun 	if (is_skx_based_platform())
2036*4882a593Smuzhiyun 		clos_priority_type = 1;
2037*4882a593Smuzhiyun 
2038*4882a593Smuzhiyun 	ret = isst_pm_qos_config(cpu, status, clos_priority_type);
2039*4882a593Smuzhiyun 	if (ret)
2040*4882a593Smuzhiyun 		isst_display_error_info_message(1, "isst_pm_qos_config failed", 0, 0);
2041*4882a593Smuzhiyun 
2042*4882a593Smuzhiyun 	if (status)
2043*4882a593Smuzhiyun 		isst_display_result(cpu, outf, "core-power", "enable",
2044*4882a593Smuzhiyun 				    ret);
2045*4882a593Smuzhiyun 	else
2046*4882a593Smuzhiyun 		isst_display_result(cpu, outf, "core-power", "disable",
2047*4882a593Smuzhiyun 				    ret);
2048*4882a593Smuzhiyun }
2049*4882a593Smuzhiyun 
set_clos_enable(int arg)2050*4882a593Smuzhiyun static void set_clos_enable(int arg)
2051*4882a593Smuzhiyun {
2052*4882a593Smuzhiyun 	int enable = arg;
2053*4882a593Smuzhiyun 
2054*4882a593Smuzhiyun 	if (cmd_help) {
2055*4882a593Smuzhiyun 		if (enable) {
2056*4882a593Smuzhiyun 			fprintf(stderr,
2057*4882a593Smuzhiyun 				"Enable core-power for a package/die\n");
2058*4882a593Smuzhiyun 			if (!is_skx_based_platform()) {
2059*4882a593Smuzhiyun 				fprintf(stderr,
2060*4882a593Smuzhiyun 					"\tClos Enable: Specify priority type with [--priority|-p]\n");
2061*4882a593Smuzhiyun 				fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n");
2062*4882a593Smuzhiyun 			}
2063*4882a593Smuzhiyun 		} else {
2064*4882a593Smuzhiyun 			fprintf(stderr,
2065*4882a593Smuzhiyun 				"Disable core-power: [No command arguments are required]\n");
2066*4882a593Smuzhiyun 		}
2067*4882a593Smuzhiyun 		exit(0);
2068*4882a593Smuzhiyun 	}
2069*4882a593Smuzhiyun 
2070*4882a593Smuzhiyun 	if (enable && cpufreq_sysfs_present()) {
2071*4882a593Smuzhiyun 		fprintf(stderr,
2072*4882a593Smuzhiyun 			"cpufreq subsystem and core-power enable will interfere with each other!\n");
2073*4882a593Smuzhiyun 	}
2074*4882a593Smuzhiyun 
2075*4882a593Smuzhiyun 	isst_ctdp_display_information_start(outf);
2076*4882a593Smuzhiyun 	if (max_target_cpus)
2077*4882a593Smuzhiyun 		for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
2078*4882a593Smuzhiyun 						  NULL, NULL, &enable);
2079*4882a593Smuzhiyun 	else
2080*4882a593Smuzhiyun 		for_each_online_package_in_set(enable_clos_qos_config, NULL,
2081*4882a593Smuzhiyun 					       NULL, NULL, &enable);
2082*4882a593Smuzhiyun 	isst_ctdp_display_information_end(outf);
2083*4882a593Smuzhiyun }
2084*4882a593Smuzhiyun 
dump_clos_config_for_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)2085*4882a593Smuzhiyun static void dump_clos_config_for_cpu(int cpu, void *arg1, void *arg2,
2086*4882a593Smuzhiyun 				     void *arg3, void *arg4)
2087*4882a593Smuzhiyun {
2088*4882a593Smuzhiyun 	struct isst_clos_config clos_config;
2089*4882a593Smuzhiyun 	int ret;
2090*4882a593Smuzhiyun 
2091*4882a593Smuzhiyun 	ret = isst_pm_get_clos(cpu, current_clos, &clos_config);
2092*4882a593Smuzhiyun 	if (ret)
2093*4882a593Smuzhiyun 		isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
2094*4882a593Smuzhiyun 	else
2095*4882a593Smuzhiyun 		isst_clos_display_information(cpu, outf, current_clos,
2096*4882a593Smuzhiyun 					      &clos_config);
2097*4882a593Smuzhiyun }
2098*4882a593Smuzhiyun 
dump_clos_config(int arg)2099*4882a593Smuzhiyun static void dump_clos_config(int arg)
2100*4882a593Smuzhiyun {
2101*4882a593Smuzhiyun 	if (cmd_help) {
2102*4882a593Smuzhiyun 		fprintf(stderr,
2103*4882a593Smuzhiyun 			"Print Intel Speed Select Technology core power configuration\n");
2104*4882a593Smuzhiyun 		fprintf(stderr,
2105*4882a593Smuzhiyun 			"\tArguments: [-c | --clos]: Specify clos id\n");
2106*4882a593Smuzhiyun 		exit(0);
2107*4882a593Smuzhiyun 	}
2108*4882a593Smuzhiyun 	if (current_clos < 0 || current_clos > 3) {
2109*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
2110*4882a593Smuzhiyun 		isst_ctdp_display_information_end(outf);
2111*4882a593Smuzhiyun 		exit(0);
2112*4882a593Smuzhiyun 	}
2113*4882a593Smuzhiyun 
2114*4882a593Smuzhiyun 	isst_ctdp_display_information_start(outf);
2115*4882a593Smuzhiyun 	if (max_target_cpus)
2116*4882a593Smuzhiyun 		for_each_online_target_cpu_in_set(dump_clos_config_for_cpu,
2117*4882a593Smuzhiyun 						  NULL, NULL, NULL, NULL);
2118*4882a593Smuzhiyun 	else
2119*4882a593Smuzhiyun 		for_each_online_package_in_set(dump_clos_config_for_cpu, NULL,
2120*4882a593Smuzhiyun 					       NULL, NULL, NULL);
2121*4882a593Smuzhiyun 	isst_ctdp_display_information_end(outf);
2122*4882a593Smuzhiyun }
2123*4882a593Smuzhiyun 
get_clos_info_for_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)2124*4882a593Smuzhiyun static void get_clos_info_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
2125*4882a593Smuzhiyun 				  void *arg4)
2126*4882a593Smuzhiyun {
2127*4882a593Smuzhiyun 	int enable, ret, prio_type;
2128*4882a593Smuzhiyun 
2129*4882a593Smuzhiyun 	ret = isst_clos_get_clos_information(cpu, &enable, &prio_type);
2130*4882a593Smuzhiyun 	if (ret)
2131*4882a593Smuzhiyun 		isst_display_error_info_message(1, "isst_clos_get_info failed", 0, 0);
2132*4882a593Smuzhiyun 	else {
2133*4882a593Smuzhiyun 		int cp_state, cp_cap;
2134*4882a593Smuzhiyun 
2135*4882a593Smuzhiyun 		isst_read_pm_config(cpu, &cp_state, &cp_cap);
2136*4882a593Smuzhiyun 		isst_clos_display_clos_information(cpu, outf, enable, prio_type,
2137*4882a593Smuzhiyun 						   cp_state, cp_cap);
2138*4882a593Smuzhiyun 	}
2139*4882a593Smuzhiyun }
2140*4882a593Smuzhiyun 
dump_clos_info(int arg)2141*4882a593Smuzhiyun static void dump_clos_info(int arg)
2142*4882a593Smuzhiyun {
2143*4882a593Smuzhiyun 	if (cmd_help) {
2144*4882a593Smuzhiyun 		fprintf(stderr,
2145*4882a593Smuzhiyun 			"Print Intel Speed Select Technology core power information\n");
2146*4882a593Smuzhiyun 		fprintf(stderr, "\t Optionally specify targeted cpu id with [--cpu|-c]\n");
2147*4882a593Smuzhiyun 		exit(0);
2148*4882a593Smuzhiyun 	}
2149*4882a593Smuzhiyun 
2150*4882a593Smuzhiyun 	isst_ctdp_display_information_start(outf);
2151*4882a593Smuzhiyun 	if (max_target_cpus)
2152*4882a593Smuzhiyun 		for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL,
2153*4882a593Smuzhiyun 						  NULL, NULL, NULL);
2154*4882a593Smuzhiyun 	else
2155*4882a593Smuzhiyun 		for_each_online_package_in_set(get_clos_info_for_cpu, NULL,
2156*4882a593Smuzhiyun 					       NULL, NULL, NULL);
2157*4882a593Smuzhiyun 	isst_ctdp_display_information_end(outf);
2158*4882a593Smuzhiyun 
2159*4882a593Smuzhiyun }
2160*4882a593Smuzhiyun 
set_clos_config_for_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)2161*4882a593Smuzhiyun static void set_clos_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
2162*4882a593Smuzhiyun 				    void *arg4)
2163*4882a593Smuzhiyun {
2164*4882a593Smuzhiyun 	struct isst_clos_config clos_config;
2165*4882a593Smuzhiyun 	int ret;
2166*4882a593Smuzhiyun 
2167*4882a593Smuzhiyun 	clos_config.pkg_id = get_physical_package_id(cpu);
2168*4882a593Smuzhiyun 	clos_config.die_id = get_physical_die_id(cpu);
2169*4882a593Smuzhiyun 
2170*4882a593Smuzhiyun 	clos_config.epp = clos_epp;
2171*4882a593Smuzhiyun 	clos_config.clos_prop_prio = clos_prop_prio;
2172*4882a593Smuzhiyun 	clos_config.clos_min = clos_min;
2173*4882a593Smuzhiyun 	clos_config.clos_max = clos_max;
2174*4882a593Smuzhiyun 	clos_config.clos_desired = clos_desired;
2175*4882a593Smuzhiyun 	ret = isst_set_clos(cpu, current_clos, &clos_config);
2176*4882a593Smuzhiyun 	if (ret)
2177*4882a593Smuzhiyun 		isst_display_error_info_message(1, "isst_set_clos failed", 0, 0);
2178*4882a593Smuzhiyun 	else
2179*4882a593Smuzhiyun 		isst_display_result(cpu, outf, "core-power", "config", ret);
2180*4882a593Smuzhiyun }
2181*4882a593Smuzhiyun 
set_clos_config(int arg)2182*4882a593Smuzhiyun static void set_clos_config(int arg)
2183*4882a593Smuzhiyun {
2184*4882a593Smuzhiyun 	if (cmd_help) {
2185*4882a593Smuzhiyun 		fprintf(stderr,
2186*4882a593Smuzhiyun 			"Set core-power configuration for one of the four clos ids\n");
2187*4882a593Smuzhiyun 		fprintf(stderr,
2188*4882a593Smuzhiyun 			"\tSpecify targeted clos id with [--clos|-c]\n");
2189*4882a593Smuzhiyun 		if (!is_skx_based_platform()) {
2190*4882a593Smuzhiyun 			fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n");
2191*4882a593Smuzhiyun 			fprintf(stderr,
2192*4882a593Smuzhiyun 				"\tSpecify clos Proportional Priority [--weight|-w]\n");
2193*4882a593Smuzhiyun 		}
2194*4882a593Smuzhiyun 		fprintf(stderr, "\tSpecify clos min in MHz with [--min|-n]\n");
2195*4882a593Smuzhiyun 		fprintf(stderr, "\tSpecify clos max in MHz with [--max|-m]\n");
2196*4882a593Smuzhiyun 		exit(0);
2197*4882a593Smuzhiyun 	}
2198*4882a593Smuzhiyun 
2199*4882a593Smuzhiyun 	if (current_clos < 0 || current_clos > 3) {
2200*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
2201*4882a593Smuzhiyun 		exit(0);
2202*4882a593Smuzhiyun 	}
2203*4882a593Smuzhiyun 	if (!is_skx_based_platform() && (clos_epp < 0 || clos_epp > 0x0F)) {
2204*4882a593Smuzhiyun 		fprintf(stderr, "clos epp is not specified or invalid, default: 0\n");
2205*4882a593Smuzhiyun 		clos_epp = 0;
2206*4882a593Smuzhiyun 	}
2207*4882a593Smuzhiyun 	if (!is_skx_based_platform() && (clos_prop_prio < 0 || clos_prop_prio > 0x0F)) {
2208*4882a593Smuzhiyun 		fprintf(stderr,
2209*4882a593Smuzhiyun 			"clos frequency weight is not specified or invalid, default: 0\n");
2210*4882a593Smuzhiyun 		clos_prop_prio = 0;
2211*4882a593Smuzhiyun 	}
2212*4882a593Smuzhiyun 	if (clos_min < 0) {
2213*4882a593Smuzhiyun 		fprintf(stderr, "clos min is not specified, default: 0\n");
2214*4882a593Smuzhiyun 		clos_min = 0;
2215*4882a593Smuzhiyun 	}
2216*4882a593Smuzhiyun 	if (clos_max < 0) {
2217*4882a593Smuzhiyun 		fprintf(stderr, "clos max is not specified, default: Max frequency (ratio 0xff)\n");
2218*4882a593Smuzhiyun 		clos_max = 0xff;
2219*4882a593Smuzhiyun 	}
2220*4882a593Smuzhiyun 	if (clos_desired) {
2221*4882a593Smuzhiyun 		fprintf(stderr, "clos desired is not supported on this platform\n");
2222*4882a593Smuzhiyun 		clos_desired = 0x00;
2223*4882a593Smuzhiyun 	}
2224*4882a593Smuzhiyun 
2225*4882a593Smuzhiyun 	isst_ctdp_display_information_start(outf);
2226*4882a593Smuzhiyun 	if (max_target_cpus)
2227*4882a593Smuzhiyun 		for_each_online_target_cpu_in_set(set_clos_config_for_cpu, NULL,
2228*4882a593Smuzhiyun 						  NULL, NULL, NULL);
2229*4882a593Smuzhiyun 	else
2230*4882a593Smuzhiyun 		for_each_online_package_in_set(set_clos_config_for_cpu, NULL,
2231*4882a593Smuzhiyun 					       NULL, NULL, NULL);
2232*4882a593Smuzhiyun 	isst_ctdp_display_information_end(outf);
2233*4882a593Smuzhiyun }
2234*4882a593Smuzhiyun 
set_clos_assoc_for_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)2235*4882a593Smuzhiyun static void set_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
2236*4882a593Smuzhiyun 				   void *arg4)
2237*4882a593Smuzhiyun {
2238*4882a593Smuzhiyun 	int ret;
2239*4882a593Smuzhiyun 
2240*4882a593Smuzhiyun 	ret = isst_clos_associate(cpu, current_clos);
2241*4882a593Smuzhiyun 	if (ret)
2242*4882a593Smuzhiyun 		debug_printf("isst_clos_associate failed");
2243*4882a593Smuzhiyun 	else
2244*4882a593Smuzhiyun 		isst_display_result(cpu, outf, "core-power", "assoc", ret);
2245*4882a593Smuzhiyun }
2246*4882a593Smuzhiyun 
set_clos_assoc(int arg)2247*4882a593Smuzhiyun static void set_clos_assoc(int arg)
2248*4882a593Smuzhiyun {
2249*4882a593Smuzhiyun 	if (cmd_help) {
2250*4882a593Smuzhiyun 		fprintf(stderr, "Associate a clos id to a CPU\n");
2251*4882a593Smuzhiyun 		fprintf(stderr,
2252*4882a593Smuzhiyun 			"\tSpecify targeted clos id with [--clos|-c]\n");
2253*4882a593Smuzhiyun 		fprintf(stderr,
2254*4882a593Smuzhiyun 			"\tFor example to associate clos 1 to CPU 0: issue\n");
2255*4882a593Smuzhiyun 		fprintf(stderr,
2256*4882a593Smuzhiyun 			"\tintel-speed-select --cpu 0 core-power assoc --clos 1\n");
2257*4882a593Smuzhiyun 		exit(0);
2258*4882a593Smuzhiyun 	}
2259*4882a593Smuzhiyun 
2260*4882a593Smuzhiyun 	if (current_clos < 0 || current_clos > 3) {
2261*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
2262*4882a593Smuzhiyun 		exit(0);
2263*4882a593Smuzhiyun 	}
2264*4882a593Smuzhiyun 	if (max_target_cpus)
2265*4882a593Smuzhiyun 		for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL,
2266*4882a593Smuzhiyun 						  NULL, NULL, NULL);
2267*4882a593Smuzhiyun 	else {
2268*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0);
2269*4882a593Smuzhiyun 	}
2270*4882a593Smuzhiyun }
2271*4882a593Smuzhiyun 
get_clos_assoc_for_cpu(int cpu,void * arg1,void * arg2,void * arg3,void * arg4)2272*4882a593Smuzhiyun static void get_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
2273*4882a593Smuzhiyun 				   void *arg4)
2274*4882a593Smuzhiyun {
2275*4882a593Smuzhiyun 	int clos, ret;
2276*4882a593Smuzhiyun 
2277*4882a593Smuzhiyun 	ret = isst_clos_get_assoc_status(cpu, &clos);
2278*4882a593Smuzhiyun 	if (ret)
2279*4882a593Smuzhiyun 		isst_display_error_info_message(1, "isst_clos_get_assoc_status failed", 0, 0);
2280*4882a593Smuzhiyun 	else
2281*4882a593Smuzhiyun 		isst_clos_display_assoc_information(cpu, outf, clos);
2282*4882a593Smuzhiyun }
2283*4882a593Smuzhiyun 
get_clos_assoc(int arg)2284*4882a593Smuzhiyun static void get_clos_assoc(int arg)
2285*4882a593Smuzhiyun {
2286*4882a593Smuzhiyun 	if (cmd_help) {
2287*4882a593Smuzhiyun 		fprintf(stderr, "Get associate clos id to a CPU\n");
2288*4882a593Smuzhiyun 		fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n");
2289*4882a593Smuzhiyun 		exit(0);
2290*4882a593Smuzhiyun 	}
2291*4882a593Smuzhiyun 
2292*4882a593Smuzhiyun 	if (!max_target_cpus) {
2293*4882a593Smuzhiyun 		isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0);
2294*4882a593Smuzhiyun 		exit(0);
2295*4882a593Smuzhiyun 	}
2296*4882a593Smuzhiyun 
2297*4882a593Smuzhiyun 	isst_ctdp_display_information_start(outf);
2298*4882a593Smuzhiyun 	for_each_online_target_cpu_in_set(get_clos_assoc_for_cpu, NULL,
2299*4882a593Smuzhiyun 					  NULL, NULL, NULL);
2300*4882a593Smuzhiyun 	isst_ctdp_display_information_end(outf);
2301*4882a593Smuzhiyun }
2302*4882a593Smuzhiyun 
2303*4882a593Smuzhiyun static struct process_cmd_struct clx_n_cmds[] = {
2304*4882a593Smuzhiyun 	{ "perf-profile", "info", dump_isst_config, 0 },
2305*4882a593Smuzhiyun 	{ "base-freq", "info", dump_pbf_config, 0 },
2306*4882a593Smuzhiyun 	{ "base-freq", "enable", set_pbf_enable, 1 },
2307*4882a593Smuzhiyun 	{ "base-freq", "disable", set_pbf_enable, 0 },
2308*4882a593Smuzhiyun 	{ NULL, NULL, NULL, 0 }
2309*4882a593Smuzhiyun };
2310*4882a593Smuzhiyun 
2311*4882a593Smuzhiyun static struct process_cmd_struct isst_cmds[] = {
2312*4882a593Smuzhiyun 	{ "perf-profile", "get-lock-status", get_tdp_locked, 0 },
2313*4882a593Smuzhiyun 	{ "perf-profile", "get-config-levels", get_tdp_levels, 0 },
2314*4882a593Smuzhiyun 	{ "perf-profile", "get-config-version", get_tdp_version, 0 },
2315*4882a593Smuzhiyun 	{ "perf-profile", "get-config-enabled", get_tdp_enabled, 0 },
2316*4882a593Smuzhiyun 	{ "perf-profile", "get-config-current-level", get_tdp_current_level,
2317*4882a593Smuzhiyun 	 0 },
2318*4882a593Smuzhiyun 	{ "perf-profile", "set-config-level", set_tdp_level, 0 },
2319*4882a593Smuzhiyun 	{ "perf-profile", "info", dump_isst_config, 0 },
2320*4882a593Smuzhiyun 	{ "base-freq", "info", dump_pbf_config, 0 },
2321*4882a593Smuzhiyun 	{ "base-freq", "enable", set_pbf_enable, 1 },
2322*4882a593Smuzhiyun 	{ "base-freq", "disable", set_pbf_enable, 0 },
2323*4882a593Smuzhiyun 	{ "turbo-freq", "info", dump_fact_config, 0 },
2324*4882a593Smuzhiyun 	{ "turbo-freq", "enable", set_fact_enable, 1 },
2325*4882a593Smuzhiyun 	{ "turbo-freq", "disable", set_fact_enable, 0 },
2326*4882a593Smuzhiyun 	{ "core-power", "info", dump_clos_info, 0 },
2327*4882a593Smuzhiyun 	{ "core-power", "enable", set_clos_enable, 1 },
2328*4882a593Smuzhiyun 	{ "core-power", "disable", set_clos_enable, 0 },
2329*4882a593Smuzhiyun 	{ "core-power", "config", set_clos_config, 0 },
2330*4882a593Smuzhiyun 	{ "core-power", "get-config", dump_clos_config, 0 },
2331*4882a593Smuzhiyun 	{ "core-power", "assoc", set_clos_assoc, 0 },
2332*4882a593Smuzhiyun 	{ "core-power", "get-assoc", get_clos_assoc, 0 },
2333*4882a593Smuzhiyun 	{ NULL, NULL, NULL }
2334*4882a593Smuzhiyun };
2335*4882a593Smuzhiyun 
2336*4882a593Smuzhiyun /*
2337*4882a593Smuzhiyun  * parse cpuset with following syntax
2338*4882a593Smuzhiyun  * 1,2,4..6,8-10 and set bits in cpu_subset
2339*4882a593Smuzhiyun  */
parse_cpu_command(char * optarg)2340*4882a593Smuzhiyun void parse_cpu_command(char *optarg)
2341*4882a593Smuzhiyun {
2342*4882a593Smuzhiyun 	unsigned int start, end;
2343*4882a593Smuzhiyun 	char *next;
2344*4882a593Smuzhiyun 
2345*4882a593Smuzhiyun 	next = optarg;
2346*4882a593Smuzhiyun 
2347*4882a593Smuzhiyun 	while (next && *next) {
2348*4882a593Smuzhiyun 		if (*next == '-') /* no negative cpu numbers */
2349*4882a593Smuzhiyun 			goto error;
2350*4882a593Smuzhiyun 
2351*4882a593Smuzhiyun 		start = strtoul(next, &next, 10);
2352*4882a593Smuzhiyun 
2353*4882a593Smuzhiyun 		if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
2354*4882a593Smuzhiyun 			target_cpus[max_target_cpus++] = start;
2355*4882a593Smuzhiyun 
2356*4882a593Smuzhiyun 		if (*next == '\0')
2357*4882a593Smuzhiyun 			break;
2358*4882a593Smuzhiyun 
2359*4882a593Smuzhiyun 		if (*next == ',') {
2360*4882a593Smuzhiyun 			next += 1;
2361*4882a593Smuzhiyun 			continue;
2362*4882a593Smuzhiyun 		}
2363*4882a593Smuzhiyun 
2364*4882a593Smuzhiyun 		if (*next == '-') {
2365*4882a593Smuzhiyun 			next += 1; /* start range */
2366*4882a593Smuzhiyun 		} else if (*next == '.') {
2367*4882a593Smuzhiyun 			next += 1;
2368*4882a593Smuzhiyun 			if (*next == '.')
2369*4882a593Smuzhiyun 				next += 1; /* start range */
2370*4882a593Smuzhiyun 			else
2371*4882a593Smuzhiyun 				goto error;
2372*4882a593Smuzhiyun 		}
2373*4882a593Smuzhiyun 
2374*4882a593Smuzhiyun 		end = strtoul(next, &next, 10);
2375*4882a593Smuzhiyun 		if (end <= start)
2376*4882a593Smuzhiyun 			goto error;
2377*4882a593Smuzhiyun 
2378*4882a593Smuzhiyun 		while (++start <= end) {
2379*4882a593Smuzhiyun 			if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
2380*4882a593Smuzhiyun 				target_cpus[max_target_cpus++] = start;
2381*4882a593Smuzhiyun 		}
2382*4882a593Smuzhiyun 
2383*4882a593Smuzhiyun 		if (*next == ',')
2384*4882a593Smuzhiyun 			next += 1;
2385*4882a593Smuzhiyun 		else if (*next != '\0')
2386*4882a593Smuzhiyun 			goto error;
2387*4882a593Smuzhiyun 	}
2388*4882a593Smuzhiyun 
2389*4882a593Smuzhiyun #ifdef DEBUG
2390*4882a593Smuzhiyun 	{
2391*4882a593Smuzhiyun 		int i;
2392*4882a593Smuzhiyun 
2393*4882a593Smuzhiyun 		for (i = 0; i < max_target_cpus; ++i)
2394*4882a593Smuzhiyun 			printf("cpu [%d] in arg\n", target_cpus[i]);
2395*4882a593Smuzhiyun 	}
2396*4882a593Smuzhiyun #endif
2397*4882a593Smuzhiyun 	return;
2398*4882a593Smuzhiyun 
2399*4882a593Smuzhiyun error:
2400*4882a593Smuzhiyun 	fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);
2401*4882a593Smuzhiyun 	exit(-1);
2402*4882a593Smuzhiyun }
2403*4882a593Smuzhiyun 
parse_cmd_args(int argc,int start,char ** argv)2404*4882a593Smuzhiyun static void parse_cmd_args(int argc, int start, char **argv)
2405*4882a593Smuzhiyun {
2406*4882a593Smuzhiyun 	int opt;
2407*4882a593Smuzhiyun 	int option_index;
2408*4882a593Smuzhiyun 
2409*4882a593Smuzhiyun 	static struct option long_options[] = {
2410*4882a593Smuzhiyun 		{ "bucket", required_argument, 0, 'b' },
2411*4882a593Smuzhiyun 		{ "level", required_argument, 0, 'l' },
2412*4882a593Smuzhiyun 		{ "online", required_argument, 0, 'o' },
2413*4882a593Smuzhiyun 		{ "trl-type", required_argument, 0, 'r' },
2414*4882a593Smuzhiyun 		{ "trl", required_argument, 0, 't' },
2415*4882a593Smuzhiyun 		{ "help", no_argument, 0, 'h' },
2416*4882a593Smuzhiyun 		{ "clos", required_argument, 0, 'c' },
2417*4882a593Smuzhiyun 		{ "desired", required_argument, 0, 'd' },
2418*4882a593Smuzhiyun 		{ "epp", required_argument, 0, 'e' },
2419*4882a593Smuzhiyun 		{ "min", required_argument, 0, 'n' },
2420*4882a593Smuzhiyun 		{ "max", required_argument, 0, 'm' },
2421*4882a593Smuzhiyun 		{ "priority", required_argument, 0, 'p' },
2422*4882a593Smuzhiyun 		{ "weight", required_argument, 0, 'w' },
2423*4882a593Smuzhiyun 		{ "auto", no_argument, 0, 'a' },
2424*4882a593Smuzhiyun 		{ 0, 0, 0, 0 }
2425*4882a593Smuzhiyun 	};
2426*4882a593Smuzhiyun 
2427*4882a593Smuzhiyun 	option_index = start;
2428*4882a593Smuzhiyun 
2429*4882a593Smuzhiyun 	optind = start + 1;
2430*4882a593Smuzhiyun 	while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:r:hoa",
2431*4882a593Smuzhiyun 				  long_options, &option_index)) != -1) {
2432*4882a593Smuzhiyun 		switch (opt) {
2433*4882a593Smuzhiyun 		case 'a':
2434*4882a593Smuzhiyun 			auto_mode = 1;
2435*4882a593Smuzhiyun 			break;
2436*4882a593Smuzhiyun 		case 'b':
2437*4882a593Smuzhiyun 			fact_bucket = atoi(optarg);
2438*4882a593Smuzhiyun 			break;
2439*4882a593Smuzhiyun 		case 'h':
2440*4882a593Smuzhiyun 			cmd_help = 1;
2441*4882a593Smuzhiyun 			break;
2442*4882a593Smuzhiyun 		case 'l':
2443*4882a593Smuzhiyun 			tdp_level = atoi(optarg);
2444*4882a593Smuzhiyun 			break;
2445*4882a593Smuzhiyun 		case 'o':
2446*4882a593Smuzhiyun 			force_online_offline = 1;
2447*4882a593Smuzhiyun 			break;
2448*4882a593Smuzhiyun 		case 't':
2449*4882a593Smuzhiyun 			sscanf(optarg, "0x%llx", &fact_trl);
2450*4882a593Smuzhiyun 			break;
2451*4882a593Smuzhiyun 		case 'r':
2452*4882a593Smuzhiyun 			if (!strncmp(optarg, "sse", 3)) {
2453*4882a593Smuzhiyun 				fact_avx = 0x01;
2454*4882a593Smuzhiyun 			} else if (!strncmp(optarg, "avx2", 4)) {
2455*4882a593Smuzhiyun 				fact_avx = 0x02;
2456*4882a593Smuzhiyun 			} else if (!strncmp(optarg, "avx512", 6)) {
2457*4882a593Smuzhiyun 				fact_avx = 0x04;
2458*4882a593Smuzhiyun 			} else {
2459*4882a593Smuzhiyun 				fprintf(outf, "Invalid sse,avx options\n");
2460*4882a593Smuzhiyun 				exit(1);
2461*4882a593Smuzhiyun 			}
2462*4882a593Smuzhiyun 			break;
2463*4882a593Smuzhiyun 		/* CLOS related */
2464*4882a593Smuzhiyun 		case 'c':
2465*4882a593Smuzhiyun 			current_clos = atoi(optarg);
2466*4882a593Smuzhiyun 			break;
2467*4882a593Smuzhiyun 		case 'd':
2468*4882a593Smuzhiyun 			clos_desired = atoi(optarg);
2469*4882a593Smuzhiyun 			clos_desired /= DISP_FREQ_MULTIPLIER;
2470*4882a593Smuzhiyun 			break;
2471*4882a593Smuzhiyun 		case 'e':
2472*4882a593Smuzhiyun 			clos_epp = atoi(optarg);
2473*4882a593Smuzhiyun 			if (is_skx_based_platform()) {
2474*4882a593Smuzhiyun 				isst_display_error_info_message(1, "epp can't be specified on this platform", 0, 0);
2475*4882a593Smuzhiyun 				exit(0);
2476*4882a593Smuzhiyun 			}
2477*4882a593Smuzhiyun 			break;
2478*4882a593Smuzhiyun 		case 'n':
2479*4882a593Smuzhiyun 			clos_min = atoi(optarg);
2480*4882a593Smuzhiyun 			clos_min /= DISP_FREQ_MULTIPLIER;
2481*4882a593Smuzhiyun 			break;
2482*4882a593Smuzhiyun 		case 'm':
2483*4882a593Smuzhiyun 			clos_max = atoi(optarg);
2484*4882a593Smuzhiyun 			clos_max /= DISP_FREQ_MULTIPLIER;
2485*4882a593Smuzhiyun 			break;
2486*4882a593Smuzhiyun 		case 'p':
2487*4882a593Smuzhiyun 			clos_priority_type = atoi(optarg);
2488*4882a593Smuzhiyun 			if (is_skx_based_platform() && !clos_priority_type) {
2489*4882a593Smuzhiyun 				isst_display_error_info_message(1, "Invalid clos priority type: proportional for this platform", 0, 0);
2490*4882a593Smuzhiyun 				exit(0);
2491*4882a593Smuzhiyun 			}
2492*4882a593Smuzhiyun 			break;
2493*4882a593Smuzhiyun 		case 'w':
2494*4882a593Smuzhiyun 			clos_prop_prio = atoi(optarg);
2495*4882a593Smuzhiyun 			if (is_skx_based_platform()) {
2496*4882a593Smuzhiyun 				isst_display_error_info_message(1, "weight can't be specified on this platform", 0, 0);
2497*4882a593Smuzhiyun 				exit(0);
2498*4882a593Smuzhiyun 			}
2499*4882a593Smuzhiyun 			break;
2500*4882a593Smuzhiyun 		default:
2501*4882a593Smuzhiyun 			printf("Unknown option: ignore\n");
2502*4882a593Smuzhiyun 		}
2503*4882a593Smuzhiyun 	}
2504*4882a593Smuzhiyun 
2505*4882a593Smuzhiyun 	if (argv[optind])
2506*4882a593Smuzhiyun 		printf("Garbage at the end of command: ignore\n");
2507*4882a593Smuzhiyun }
2508*4882a593Smuzhiyun 
isst_help(void)2509*4882a593Smuzhiyun static void isst_help(void)
2510*4882a593Smuzhiyun {
2511*4882a593Smuzhiyun 	printf("perf-profile:\tAn architectural mechanism that allows multiple optimized \n\
2512*4882a593Smuzhiyun 		performance profiles per system via static and/or dynamic\n\
2513*4882a593Smuzhiyun 		adjustment of core count, workload, Tjmax, and\n\
2514*4882a593Smuzhiyun 		TDP, etc.\n");
2515*4882a593Smuzhiyun 	printf("\nCommands : For feature=perf-profile\n");
2516*4882a593Smuzhiyun 	printf("\tinfo\n");
2517*4882a593Smuzhiyun 
2518*4882a593Smuzhiyun 	if (!is_clx_n_platform()) {
2519*4882a593Smuzhiyun 		printf("\tget-lock-status\n");
2520*4882a593Smuzhiyun 		printf("\tget-config-levels\n");
2521*4882a593Smuzhiyun 		printf("\tget-config-version\n");
2522*4882a593Smuzhiyun 		printf("\tget-config-enabled\n");
2523*4882a593Smuzhiyun 		printf("\tget-config-current-level\n");
2524*4882a593Smuzhiyun 		printf("\tset-config-level\n");
2525*4882a593Smuzhiyun 	}
2526*4882a593Smuzhiyun }
2527*4882a593Smuzhiyun 
pbf_help(void)2528*4882a593Smuzhiyun static void pbf_help(void)
2529*4882a593Smuzhiyun {
2530*4882a593Smuzhiyun 	printf("base-freq:\tEnables users to increase guaranteed base frequency\n\
2531*4882a593Smuzhiyun 		on certain cores (high priority cores) in exchange for lower\n\
2532*4882a593Smuzhiyun 		base frequency on remaining cores (low priority cores).\n");
2533*4882a593Smuzhiyun 	printf("\tcommand : info\n");
2534*4882a593Smuzhiyun 	printf("\tcommand : enable\n");
2535*4882a593Smuzhiyun 	printf("\tcommand : disable\n");
2536*4882a593Smuzhiyun }
2537*4882a593Smuzhiyun 
fact_help(void)2538*4882a593Smuzhiyun static void fact_help(void)
2539*4882a593Smuzhiyun {
2540*4882a593Smuzhiyun 	printf("turbo-freq:\tEnables the ability to set different turbo ratio\n\
2541*4882a593Smuzhiyun 		limits to cores based on priority.\n");
2542*4882a593Smuzhiyun 	printf("\nCommand: For feature=turbo-freq\n");
2543*4882a593Smuzhiyun 	printf("\tcommand : info\n");
2544*4882a593Smuzhiyun 	printf("\tcommand : enable\n");
2545*4882a593Smuzhiyun 	printf("\tcommand : disable\n");
2546*4882a593Smuzhiyun }
2547*4882a593Smuzhiyun 
core_power_help(void)2548*4882a593Smuzhiyun static void core_power_help(void)
2549*4882a593Smuzhiyun {
2550*4882a593Smuzhiyun 	printf("core-power:\tInterface that allows user to define per core/tile\n\
2551*4882a593Smuzhiyun 		priority.\n");
2552*4882a593Smuzhiyun 	printf("\nCommands : For feature=core-power\n");
2553*4882a593Smuzhiyun 	printf("\tinfo\n");
2554*4882a593Smuzhiyun 	printf("\tenable\n");
2555*4882a593Smuzhiyun 	printf("\tdisable\n");
2556*4882a593Smuzhiyun 	printf("\tconfig\n");
2557*4882a593Smuzhiyun 	printf("\tget-config\n");
2558*4882a593Smuzhiyun 	printf("\tassoc\n");
2559*4882a593Smuzhiyun 	printf("\tget-assoc\n");
2560*4882a593Smuzhiyun }
2561*4882a593Smuzhiyun 
2562*4882a593Smuzhiyun struct process_cmd_help_struct {
2563*4882a593Smuzhiyun 	char *feature;
2564*4882a593Smuzhiyun 	void (*process_fn)(void);
2565*4882a593Smuzhiyun };
2566*4882a593Smuzhiyun 
2567*4882a593Smuzhiyun static struct process_cmd_help_struct isst_help_cmds[] = {
2568*4882a593Smuzhiyun 	{ "perf-profile", isst_help },
2569*4882a593Smuzhiyun 	{ "base-freq", pbf_help },
2570*4882a593Smuzhiyun 	{ "turbo-freq", fact_help },
2571*4882a593Smuzhiyun 	{ "core-power", core_power_help },
2572*4882a593Smuzhiyun 	{ NULL, NULL }
2573*4882a593Smuzhiyun };
2574*4882a593Smuzhiyun 
2575*4882a593Smuzhiyun static struct process_cmd_help_struct clx_n_help_cmds[] = {
2576*4882a593Smuzhiyun 	{ "perf-profile", isst_help },
2577*4882a593Smuzhiyun 	{ "base-freq", pbf_help },
2578*4882a593Smuzhiyun 	{ NULL, NULL }
2579*4882a593Smuzhiyun };
2580*4882a593Smuzhiyun 
process_command(int argc,char ** argv,struct process_cmd_help_struct * help_cmds,struct process_cmd_struct * cmds)2581*4882a593Smuzhiyun void process_command(int argc, char **argv,
2582*4882a593Smuzhiyun 		     struct process_cmd_help_struct *help_cmds,
2583*4882a593Smuzhiyun 		     struct process_cmd_struct *cmds)
2584*4882a593Smuzhiyun {
2585*4882a593Smuzhiyun 	int i = 0, matched = 0;
2586*4882a593Smuzhiyun 	char *feature = argv[optind];
2587*4882a593Smuzhiyun 	char *cmd = argv[optind + 1];
2588*4882a593Smuzhiyun 
2589*4882a593Smuzhiyun 	if (!feature || !cmd)
2590*4882a593Smuzhiyun 		return;
2591*4882a593Smuzhiyun 
2592*4882a593Smuzhiyun 	debug_printf("feature name [%s] command [%s]\n", feature, cmd);
2593*4882a593Smuzhiyun 	if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) {
2594*4882a593Smuzhiyun 		while (help_cmds[i].feature) {
2595*4882a593Smuzhiyun 			if (!strcmp(help_cmds[i].feature, feature)) {
2596*4882a593Smuzhiyun 				help_cmds[i].process_fn();
2597*4882a593Smuzhiyun 				exit(0);
2598*4882a593Smuzhiyun 			}
2599*4882a593Smuzhiyun 			++i;
2600*4882a593Smuzhiyun 		}
2601*4882a593Smuzhiyun 	}
2602*4882a593Smuzhiyun 
2603*4882a593Smuzhiyun 	if (!is_clx_n_platform())
2604*4882a593Smuzhiyun 		create_cpu_map();
2605*4882a593Smuzhiyun 
2606*4882a593Smuzhiyun 	i = 0;
2607*4882a593Smuzhiyun 	while (cmds[i].feature) {
2608*4882a593Smuzhiyun 		if (!strcmp(cmds[i].feature, feature) &&
2609*4882a593Smuzhiyun 		    !strcmp(cmds[i].command, cmd)) {
2610*4882a593Smuzhiyun 			parse_cmd_args(argc, optind + 1, argv);
2611*4882a593Smuzhiyun 			cmds[i].process_fn(cmds[i].arg);
2612*4882a593Smuzhiyun 			matched = 1;
2613*4882a593Smuzhiyun 			break;
2614*4882a593Smuzhiyun 		}
2615*4882a593Smuzhiyun 		++i;
2616*4882a593Smuzhiyun 	}
2617*4882a593Smuzhiyun 
2618*4882a593Smuzhiyun 	if (!matched)
2619*4882a593Smuzhiyun 		fprintf(stderr, "Invalid command\n");
2620*4882a593Smuzhiyun }
2621*4882a593Smuzhiyun 
usage(void)2622*4882a593Smuzhiyun static void usage(void)
2623*4882a593Smuzhiyun {
2624*4882a593Smuzhiyun 	if (is_clx_n_platform()) {
2625*4882a593Smuzhiyun 		fprintf(stderr, "\nThere is limited support of Intel Speed Select features on this platform.\n");
2626*4882a593Smuzhiyun 		fprintf(stderr, "Everything is pre-configured using BIOS options, this tool can't enable any feature in the hardware.\n\n");
2627*4882a593Smuzhiyun 	}
2628*4882a593Smuzhiyun 
2629*4882a593Smuzhiyun 	printf("\nUsage:\n");
2630*4882a593Smuzhiyun 	printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n");
2631*4882a593Smuzhiyun 	printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features:\n");
2632*4882a593Smuzhiyun 	if (is_clx_n_platform())
2633*4882a593Smuzhiyun 		printf("\nFEATURE : [perf-profile|base-freq]\n");
2634*4882a593Smuzhiyun 	else
2635*4882a593Smuzhiyun 		printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power]\n");
2636*4882a593Smuzhiyun 	printf("\nFor help on each feature, use -h|--help\n");
2637*4882a593Smuzhiyun 	printf("\tFor example:  intel-speed-select perf-profile -h\n");
2638*4882a593Smuzhiyun 
2639*4882a593Smuzhiyun 	printf("\nFor additional help on each command for a feature, use --h|--help\n");
2640*4882a593Smuzhiyun 	printf("\tFor example:  intel-speed-select perf-profile get-lock-status -h\n");
2641*4882a593Smuzhiyun 	printf("\t\t This will print help for the command \"get-lock-status\" for the feature \"perf-profile\"\n");
2642*4882a593Smuzhiyun 
2643*4882a593Smuzhiyun 	printf("\nOPTIONS\n");
2644*4882a593Smuzhiyun 	printf("\t[-c|--cpu] : logical cpu number\n");
2645*4882a593Smuzhiyun 	printf("\t\tDefault: Die scoped for all dies in the system with multiple dies/package\n");
2646*4882a593Smuzhiyun 	printf("\t\t\t Or Package scoped for all Packages when each package contains one die\n");
2647*4882a593Smuzhiyun 	printf("\t[-d|--debug] : Debug mode\n");
2648*4882a593Smuzhiyun 	printf("\t[-f|--format] : output format [json|text]. Default: text\n");
2649*4882a593Smuzhiyun 	printf("\t[-h|--help] : Print help\n");
2650*4882a593Smuzhiyun 	printf("\t[-i|--info] : Print platform information\n");
2651*4882a593Smuzhiyun 	printf("\t[-o|--out] : Output file\n");
2652*4882a593Smuzhiyun 	printf("\t\t\tDefault : stderr\n");
2653*4882a593Smuzhiyun 	printf("\t[-p|--pause] : Delay between two mail box commands in milliseconds\n");
2654*4882a593Smuzhiyun 	printf("\t[-r|--retry] : Retry count for mail box commands on failure, default 3\n");
2655*4882a593Smuzhiyun 	printf("\t[-v|--version] : Print version\n");
2656*4882a593Smuzhiyun 
2657*4882a593Smuzhiyun 	printf("\nResult format\n");
2658*4882a593Smuzhiyun 	printf("\tResult display uses a common format for each command:\n");
2659*4882a593Smuzhiyun 	printf("\tResults are formatted in text/JSON with\n");
2660*4882a593Smuzhiyun 	printf("\t\tPackage, Die, CPU, and command specific results.\n");
2661*4882a593Smuzhiyun 
2662*4882a593Smuzhiyun 	printf("\nExamples\n");
2663*4882a593Smuzhiyun 	printf("\tTo get platform information:\n");
2664*4882a593Smuzhiyun 	printf("\t\tintel-speed-select --info\n");
2665*4882a593Smuzhiyun 	printf("\tTo get full perf-profile information dump:\n");
2666*4882a593Smuzhiyun 	printf("\t\tintel-speed-select perf-profile info\n");
2667*4882a593Smuzhiyun 	printf("\tTo get full base-freq information dump:\n");
2668*4882a593Smuzhiyun 	printf("\t\tintel-speed-select base-freq info -l 0\n");
2669*4882a593Smuzhiyun 	if (!is_clx_n_platform()) {
2670*4882a593Smuzhiyun 		printf("\tTo get full turbo-freq information dump:\n");
2671*4882a593Smuzhiyun 		printf("\t\tintel-speed-select turbo-freq info -l 0\n");
2672*4882a593Smuzhiyun 	}
2673*4882a593Smuzhiyun 	exit(1);
2674*4882a593Smuzhiyun }
2675*4882a593Smuzhiyun 
print_version(void)2676*4882a593Smuzhiyun static void print_version(void)
2677*4882a593Smuzhiyun {
2678*4882a593Smuzhiyun 	fprintf(outf, "Version %s\n", version_str);
2679*4882a593Smuzhiyun 	fprintf(outf, "Build date %s time %s\n", __DATE__, __TIME__);
2680*4882a593Smuzhiyun 	exit(0);
2681*4882a593Smuzhiyun }
2682*4882a593Smuzhiyun 
cmdline(int argc,char ** argv)2683*4882a593Smuzhiyun static void cmdline(int argc, char **argv)
2684*4882a593Smuzhiyun {
2685*4882a593Smuzhiyun 	const char *pathname = "/dev/isst_interface";
2686*4882a593Smuzhiyun 	char *ptr;
2687*4882a593Smuzhiyun 	FILE *fp;
2688*4882a593Smuzhiyun 	int opt;
2689*4882a593Smuzhiyun 	int option_index = 0;
2690*4882a593Smuzhiyun 	int ret;
2691*4882a593Smuzhiyun 
2692*4882a593Smuzhiyun 	static struct option long_options[] = {
2693*4882a593Smuzhiyun 		{ "cpu", required_argument, 0, 'c' },
2694*4882a593Smuzhiyun 		{ "debug", no_argument, 0, 'd' },
2695*4882a593Smuzhiyun 		{ "format", required_argument, 0, 'f' },
2696*4882a593Smuzhiyun 		{ "help", no_argument, 0, 'h' },
2697*4882a593Smuzhiyun 		{ "info", no_argument, 0, 'i' },
2698*4882a593Smuzhiyun 		{ "pause", required_argument, 0, 'p' },
2699*4882a593Smuzhiyun 		{ "out", required_argument, 0, 'o' },
2700*4882a593Smuzhiyun 		{ "retry", required_argument, 0, 'r' },
2701*4882a593Smuzhiyun 		{ "version", no_argument, 0, 'v' },
2702*4882a593Smuzhiyun 		{ 0, 0, 0, 0 }
2703*4882a593Smuzhiyun 	};
2704*4882a593Smuzhiyun 
2705*4882a593Smuzhiyun 	if (geteuid() != 0) {
2706*4882a593Smuzhiyun 		fprintf(stderr, "Must run as root\n");
2707*4882a593Smuzhiyun 		exit(0);
2708*4882a593Smuzhiyun 	}
2709*4882a593Smuzhiyun 
2710*4882a593Smuzhiyun 	ret = update_cpu_model();
2711*4882a593Smuzhiyun 	if (ret)
2712*4882a593Smuzhiyun 		err(-1, "Invalid CPU model (%d)\n", cpu_model);
2713*4882a593Smuzhiyun 	printf("Intel(R) Speed Select Technology\n");
2714*4882a593Smuzhiyun 	printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model);
2715*4882a593Smuzhiyun 
2716*4882a593Smuzhiyun 	if (!is_clx_n_platform()) {
2717*4882a593Smuzhiyun 		fp = fopen(pathname, "rb");
2718*4882a593Smuzhiyun 		if (!fp) {
2719*4882a593Smuzhiyun 			fprintf(stderr, "Intel speed select drivers are not loaded on this system.\n");
2720*4882a593Smuzhiyun 			fprintf(stderr, "Verify that kernel config includes CONFIG_INTEL_SPEED_SELECT_INTERFACE.\n");
2721*4882a593Smuzhiyun 			fprintf(stderr, "If the config is included then this is not a supported platform.\n");
2722*4882a593Smuzhiyun 			exit(0);
2723*4882a593Smuzhiyun 		}
2724*4882a593Smuzhiyun 		fclose(fp);
2725*4882a593Smuzhiyun 	}
2726*4882a593Smuzhiyun 
2727*4882a593Smuzhiyun 	progname = argv[0];
2728*4882a593Smuzhiyun 	while ((opt = getopt_long_only(argc, argv, "+c:df:hio:v", long_options,
2729*4882a593Smuzhiyun 				       &option_index)) != -1) {
2730*4882a593Smuzhiyun 		switch (opt) {
2731*4882a593Smuzhiyun 		case 'c':
2732*4882a593Smuzhiyun 			parse_cpu_command(optarg);
2733*4882a593Smuzhiyun 			break;
2734*4882a593Smuzhiyun 		case 'd':
2735*4882a593Smuzhiyun 			debug_flag = 1;
2736*4882a593Smuzhiyun 			printf("Debug Mode ON\n");
2737*4882a593Smuzhiyun 			break;
2738*4882a593Smuzhiyun 		case 'f':
2739*4882a593Smuzhiyun 			if (!strncmp(optarg, "json", 4))
2740*4882a593Smuzhiyun 				out_format_json = 1;
2741*4882a593Smuzhiyun 			break;
2742*4882a593Smuzhiyun 		case 'h':
2743*4882a593Smuzhiyun 			usage();
2744*4882a593Smuzhiyun 			break;
2745*4882a593Smuzhiyun 		case 'i':
2746*4882a593Smuzhiyun 			isst_print_platform_information();
2747*4882a593Smuzhiyun 			break;
2748*4882a593Smuzhiyun 		case 'o':
2749*4882a593Smuzhiyun 			if (outf)
2750*4882a593Smuzhiyun 				fclose(outf);
2751*4882a593Smuzhiyun 			outf = fopen_or_exit(optarg, "w");
2752*4882a593Smuzhiyun 			break;
2753*4882a593Smuzhiyun 		case 'p':
2754*4882a593Smuzhiyun 			ret = strtol(optarg, &ptr, 10);
2755*4882a593Smuzhiyun 			if (!ret)
2756*4882a593Smuzhiyun 				fprintf(stderr, "Invalid pause interval, ignore\n");
2757*4882a593Smuzhiyun 			else
2758*4882a593Smuzhiyun 				mbox_delay = ret;
2759*4882a593Smuzhiyun 			break;
2760*4882a593Smuzhiyun 		case 'r':
2761*4882a593Smuzhiyun 			ret = strtol(optarg, &ptr, 10);
2762*4882a593Smuzhiyun 			if (!ret)
2763*4882a593Smuzhiyun 				fprintf(stderr, "Invalid retry count, ignore\n");
2764*4882a593Smuzhiyun 			else
2765*4882a593Smuzhiyun 				mbox_retries = ret;
2766*4882a593Smuzhiyun 			break;
2767*4882a593Smuzhiyun 		case 'v':
2768*4882a593Smuzhiyun 			print_version();
2769*4882a593Smuzhiyun 			break;
2770*4882a593Smuzhiyun 		default:
2771*4882a593Smuzhiyun 			usage();
2772*4882a593Smuzhiyun 		}
2773*4882a593Smuzhiyun 	}
2774*4882a593Smuzhiyun 
2775*4882a593Smuzhiyun 	if (optind > (argc - 2)) {
2776*4882a593Smuzhiyun 		usage();
2777*4882a593Smuzhiyun 		exit(0);
2778*4882a593Smuzhiyun 	}
2779*4882a593Smuzhiyun 	set_max_cpu_num();
2780*4882a593Smuzhiyun 	store_cpu_topology();
2781*4882a593Smuzhiyun 	set_cpu_present_cpu_mask();
2782*4882a593Smuzhiyun 	set_cpu_target_cpu_mask();
2783*4882a593Smuzhiyun 
2784*4882a593Smuzhiyun 	if (!is_clx_n_platform()) {
2785*4882a593Smuzhiyun 		ret = isst_fill_platform_info();
2786*4882a593Smuzhiyun 		if (ret)
2787*4882a593Smuzhiyun 			goto out;
2788*4882a593Smuzhiyun 		process_command(argc, argv, isst_help_cmds, isst_cmds);
2789*4882a593Smuzhiyun 	} else {
2790*4882a593Smuzhiyun 		process_command(argc, argv, clx_n_help_cmds, clx_n_cmds);
2791*4882a593Smuzhiyun 	}
2792*4882a593Smuzhiyun out:
2793*4882a593Smuzhiyun 	free_cpu_set(present_cpumask);
2794*4882a593Smuzhiyun 	free_cpu_set(target_cpumask);
2795*4882a593Smuzhiyun }
2796*4882a593Smuzhiyun 
main(int argc,char ** argv)2797*4882a593Smuzhiyun int main(int argc, char **argv)
2798*4882a593Smuzhiyun {
2799*4882a593Smuzhiyun 	outf = stderr;
2800*4882a593Smuzhiyun 	cmdline(argc, argv);
2801*4882a593Smuzhiyun 	return 0;
2802*4882a593Smuzhiyun }
2803