162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Intel Speed Select -- Enumerate and control features
462306a36Sopenharmony_ci * Copyright (c) 2019 Intel Corporation.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/isst_if.h>
862306a36Sopenharmony_ci#include <sys/utsname.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "isst.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistruct process_cmd_struct {
1362306a36Sopenharmony_ci	char *feature;
1462306a36Sopenharmony_ci	char *command;
1562306a36Sopenharmony_ci	void (*process_fn)(int arg);
1662306a36Sopenharmony_ci	int arg;
1762306a36Sopenharmony_ci};
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic const char *version_str = "v1.17";
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic const int supported_api_ver = 2;
2262306a36Sopenharmony_cistatic struct isst_if_platform_info isst_platform_info;
2362306a36Sopenharmony_cistatic char *progname;
2462306a36Sopenharmony_cistatic int debug_flag;
2562306a36Sopenharmony_cistatic FILE *outf;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistatic int cpu_model;
2862306a36Sopenharmony_cistatic int cpu_stepping;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define MAX_CPUS_IN_ONE_REQ 256
3162306a36Sopenharmony_cistatic short max_target_cpus;
3262306a36Sopenharmony_cistatic unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ];
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic int topo_max_cpus;
3562306a36Sopenharmony_cistatic size_t present_cpumask_size;
3662306a36Sopenharmony_cistatic cpu_set_t *present_cpumask;
3762306a36Sopenharmony_cistatic size_t target_cpumask_size;
3862306a36Sopenharmony_cistatic cpu_set_t *target_cpumask;
3962306a36Sopenharmony_cistatic int tdp_level = 0xFF;
4062306a36Sopenharmony_cistatic int fact_bucket = 0xFF;
4162306a36Sopenharmony_cistatic int fact_avx = 0xFF;
4262306a36Sopenharmony_cistatic unsigned long long fact_trl;
4362306a36Sopenharmony_cistatic int out_format_json;
4462306a36Sopenharmony_cistatic int cmd_help;
4562306a36Sopenharmony_cistatic int force_online_offline;
4662306a36Sopenharmony_cistatic int auto_mode;
4762306a36Sopenharmony_cistatic int fact_enable_fail;
4862306a36Sopenharmony_cistatic int cgroupv2;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci/* clos related */
5162306a36Sopenharmony_cistatic int current_clos = -1;
5262306a36Sopenharmony_cistatic int clos_epp = -1;
5362306a36Sopenharmony_cistatic int clos_prop_prio = -1;
5462306a36Sopenharmony_cistatic int clos_min = -1;
5562306a36Sopenharmony_cistatic int clos_max = -1;
5662306a36Sopenharmony_cistatic int clos_desired = -1;
5762306a36Sopenharmony_cistatic int clos_priority_type;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistruct _cpu_map {
6062306a36Sopenharmony_ci	unsigned short core_id;
6162306a36Sopenharmony_ci	unsigned short pkg_id;
6262306a36Sopenharmony_ci	unsigned short die_id;
6362306a36Sopenharmony_ci	unsigned short punit_id;
6462306a36Sopenharmony_ci	unsigned short punit_cpu;
6562306a36Sopenharmony_ci	unsigned short punit_cpu_core;
6662306a36Sopenharmony_ci	unsigned short initialized;
6762306a36Sopenharmony_ci};
6862306a36Sopenharmony_cistruct _cpu_map *cpu_map;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistruct cpu_topology {
7162306a36Sopenharmony_ci	short cpu;
7262306a36Sopenharmony_ci	short core_id;
7362306a36Sopenharmony_ci	short pkg_id;
7462306a36Sopenharmony_ci	short die_id;
7562306a36Sopenharmony_ci};
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ciFILE *get_output_file(void)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	return outf;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ciint is_debug_enabled(void)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	return debug_flag;
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_civoid debug_printf(const char *format, ...)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	va_list args;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	va_start(args, format);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	if (debug_flag)
9462306a36Sopenharmony_ci		vprintf(format, args);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	va_end(args);
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ciint is_clx_n_platform(void)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	if (cpu_model == 0x55)
10362306a36Sopenharmony_ci		if (cpu_stepping == 0x6 || cpu_stepping == 0x7)
10462306a36Sopenharmony_ci			return 1;
10562306a36Sopenharmony_ci	return 0;
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ciint is_skx_based_platform(void)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	if (cpu_model == 0x55)
11162306a36Sopenharmony_ci		return 1;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	return 0;
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ciint is_spr_platform(void)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	if (cpu_model == 0x8F)
11962306a36Sopenharmony_ci		return 1;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	return 0;
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ciint is_emr_platform(void)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	if (cpu_model == 0xCF)
12762306a36Sopenharmony_ci		return 1;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	return 0;
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ciint is_icx_platform(void)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	if (cpu_model == 0x6A || cpu_model == 0x6C)
13662306a36Sopenharmony_ci		return 1;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	return 0;
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic int update_cpu_model(void)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	unsigned int ebx, ecx, edx;
14462306a36Sopenharmony_ci	unsigned int fms, family;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	__cpuid(1, fms, ebx, ecx, edx);
14762306a36Sopenharmony_ci	family = (fms >> 8) & 0xf;
14862306a36Sopenharmony_ci	cpu_model = (fms >> 4) & 0xf;
14962306a36Sopenharmony_ci	if (family == 6 || family == 0xf)
15062306a36Sopenharmony_ci		cpu_model += ((fms >> 16) & 0xf) << 4;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	cpu_stepping = fms & 0xf;
15362306a36Sopenharmony_ci	/* only three CascadeLake-N models are supported */
15462306a36Sopenharmony_ci	if (is_clx_n_platform()) {
15562306a36Sopenharmony_ci		FILE *fp;
15662306a36Sopenharmony_ci		size_t n = 0;
15762306a36Sopenharmony_ci		char *line = NULL;
15862306a36Sopenharmony_ci		int ret = 1;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci		fp = fopen("/proc/cpuinfo", "r");
16162306a36Sopenharmony_ci		if (!fp)
16262306a36Sopenharmony_ci			err(-1, "cannot open /proc/cpuinfo\n");
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci		while (getline(&line, &n, fp) > 0) {
16562306a36Sopenharmony_ci			if (strstr(line, "model name")) {
16662306a36Sopenharmony_ci				if (strstr(line, "6252N") ||
16762306a36Sopenharmony_ci				    strstr(line, "6230N") ||
16862306a36Sopenharmony_ci				    strstr(line, "5218N"))
16962306a36Sopenharmony_ci					ret = 0;
17062306a36Sopenharmony_ci				break;
17162306a36Sopenharmony_ci			}
17262306a36Sopenharmony_ci		}
17362306a36Sopenharmony_ci		free(line);
17462306a36Sopenharmony_ci		fclose(fp);
17562306a36Sopenharmony_ci		return ret;
17662306a36Sopenharmony_ci	}
17762306a36Sopenharmony_ci	return 0;
17862306a36Sopenharmony_ci}
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ciint api_version(void)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci        return isst_platform_info.api_version;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci/* Open a file, and exit on failure */
18662306a36Sopenharmony_cistatic FILE *fopen_or_exit(const char *path, const char *mode)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	FILE *filep = fopen(path, mode);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	if (!filep)
19162306a36Sopenharmony_ci		err(1, "%s: open failed", path);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	return filep;
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci/* Parse a file containing a single int */
19762306a36Sopenharmony_cistatic int parse_int_file(int fatal, const char *fmt, ...)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	va_list args;
20062306a36Sopenharmony_ci	char path[PATH_MAX];
20162306a36Sopenharmony_ci	FILE *filep;
20262306a36Sopenharmony_ci	int value;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	va_start(args, fmt);
20562306a36Sopenharmony_ci	vsnprintf(path, sizeof(path), fmt, args);
20662306a36Sopenharmony_ci	va_end(args);
20762306a36Sopenharmony_ci	if (fatal) {
20862306a36Sopenharmony_ci		filep = fopen_or_exit(path, "r");
20962306a36Sopenharmony_ci	} else {
21062306a36Sopenharmony_ci		filep = fopen(path, "r");
21162306a36Sopenharmony_ci		if (!filep)
21262306a36Sopenharmony_ci			return -1;
21362306a36Sopenharmony_ci	}
21462306a36Sopenharmony_ci	if (fscanf(filep, "%d", &value) != 1)
21562306a36Sopenharmony_ci		err(1, "%s: failed to parse number from file", path);
21662306a36Sopenharmony_ci	fclose(filep);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	return value;
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ciint cpufreq_sysfs_present(void)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	DIR *dir;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	dir = opendir("/sys/devices/system/cpu/cpu0/cpufreq");
22662306a36Sopenharmony_ci	if (dir) {
22762306a36Sopenharmony_ci		closedir(dir);
22862306a36Sopenharmony_ci		return 1;
22962306a36Sopenharmony_ci	}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	return 0;
23262306a36Sopenharmony_ci}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ciint out_format_is_json(void)
23562306a36Sopenharmony_ci{
23662306a36Sopenharmony_ci	return out_format_json;
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistatic int get_stored_topology_info(int cpu, int *core_id, int *pkg_id, int *die_id)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	const char *pathname = "/var/run/isst_cpu_topology.dat";
24262306a36Sopenharmony_ci	struct cpu_topology cpu_top;
24362306a36Sopenharmony_ci	FILE *fp;
24462306a36Sopenharmony_ci	int ret;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	fp = fopen(pathname, "rb");
24762306a36Sopenharmony_ci	if (!fp)
24862306a36Sopenharmony_ci		return -1;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	ret = fseek(fp, cpu * sizeof(cpu_top), SEEK_SET);
25162306a36Sopenharmony_ci	if (ret)
25262306a36Sopenharmony_ci		goto err_ret;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	ret = fread(&cpu_top, sizeof(cpu_top), 1, fp);
25562306a36Sopenharmony_ci	if (ret != 1) {
25662306a36Sopenharmony_ci		ret = -1;
25762306a36Sopenharmony_ci		goto err_ret;
25862306a36Sopenharmony_ci	}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	*pkg_id = cpu_top.pkg_id;
26162306a36Sopenharmony_ci	*core_id = cpu_top.core_id;
26262306a36Sopenharmony_ci	*die_id = cpu_top.die_id;
26362306a36Sopenharmony_ci	ret = 0;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cierr_ret:
26662306a36Sopenharmony_ci	fclose(fp);
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	return ret;
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_cistatic void store_cpu_topology(void)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	const char *pathname = "/var/run/isst_cpu_topology.dat";
27462306a36Sopenharmony_ci	FILE *fp;
27562306a36Sopenharmony_ci	int i;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	fp = fopen(pathname, "rb");
27862306a36Sopenharmony_ci	if (fp) {
27962306a36Sopenharmony_ci		/* Mapping already exists */
28062306a36Sopenharmony_ci		fclose(fp);
28162306a36Sopenharmony_ci		return;
28262306a36Sopenharmony_ci	}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	fp = fopen(pathname, "wb");
28562306a36Sopenharmony_ci	if (!fp) {
28662306a36Sopenharmony_ci		fprintf(stderr, "Can't create file:%s\n", pathname);
28762306a36Sopenharmony_ci		return;
28862306a36Sopenharmony_ci	}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	fprintf(stderr, "Caching topology information\n");
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	for (i = 0; i < topo_max_cpus; ++i) {
29362306a36Sopenharmony_ci		struct cpu_topology cpu_top;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci		cpu_top.core_id = parse_int_file(0,
29662306a36Sopenharmony_ci			"/sys/devices/system/cpu/cpu%d/topology/core_id", i);
29762306a36Sopenharmony_ci		if (cpu_top.core_id < 0)
29862306a36Sopenharmony_ci			cpu_top.core_id = -1;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci		cpu_top.pkg_id = parse_int_file(0,
30162306a36Sopenharmony_ci			"/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
30262306a36Sopenharmony_ci		if (cpu_top.pkg_id < 0)
30362306a36Sopenharmony_ci			cpu_top.pkg_id = -1;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci		cpu_top.die_id = parse_int_file(0,
30662306a36Sopenharmony_ci			"/sys/devices/system/cpu/cpu%d/topology/die_id", i);
30762306a36Sopenharmony_ci		if (cpu_top.die_id < 0)
30862306a36Sopenharmony_ci			cpu_top.die_id = -1;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci		cpu_top.cpu = i;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci		if (fwrite(&cpu_top, sizeof(cpu_top), 1, fp) != 1) {
31362306a36Sopenharmony_ci			fprintf(stderr, "Can't write to:%s\n", pathname);
31462306a36Sopenharmony_ci			break;
31562306a36Sopenharmony_ci		}
31662306a36Sopenharmony_ci	}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	fclose(fp);
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic int get_physical_package_id(int cpu)
32262306a36Sopenharmony_ci{
32362306a36Sopenharmony_ci	int ret;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	if (cpu < 0)
32662306a36Sopenharmony_ci		return -1;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	if (cpu_map && cpu_map[cpu].initialized)
32962306a36Sopenharmony_ci		return cpu_map[cpu].pkg_id;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	ret = parse_int_file(0,
33262306a36Sopenharmony_ci			"/sys/devices/system/cpu/cpu%d/topology/physical_package_id",
33362306a36Sopenharmony_ci			cpu);
33462306a36Sopenharmony_ci	if (ret < 0) {
33562306a36Sopenharmony_ci		int core_id, pkg_id, die_id;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci		ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
33862306a36Sopenharmony_ci		if (!ret)
33962306a36Sopenharmony_ci			return pkg_id;
34062306a36Sopenharmony_ci	}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	return ret;
34362306a36Sopenharmony_ci}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_cistatic int get_physical_core_id(int cpu)
34662306a36Sopenharmony_ci{
34762306a36Sopenharmony_ci	int ret;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	if (cpu < 0)
35062306a36Sopenharmony_ci		return -1;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	if (cpu_map && cpu_map[cpu].initialized)
35362306a36Sopenharmony_ci		return cpu_map[cpu].core_id;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	ret = parse_int_file(0,
35662306a36Sopenharmony_ci			"/sys/devices/system/cpu/cpu%d/topology/core_id",
35762306a36Sopenharmony_ci			cpu);
35862306a36Sopenharmony_ci	if (ret < 0) {
35962306a36Sopenharmony_ci		int core_id, pkg_id, die_id;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci		ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
36262306a36Sopenharmony_ci		if (!ret)
36362306a36Sopenharmony_ci			return core_id;
36462306a36Sopenharmony_ci	}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	return ret;
36762306a36Sopenharmony_ci}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_cistatic int get_physical_die_id(int cpu)
37062306a36Sopenharmony_ci{
37162306a36Sopenharmony_ci	int ret;
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	if (cpu < 0)
37462306a36Sopenharmony_ci		return -1;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	if (cpu_map && cpu_map[cpu].initialized)
37762306a36Sopenharmony_ci		return cpu_map[cpu].die_id;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	ret = parse_int_file(0,
38062306a36Sopenharmony_ci			"/sys/devices/system/cpu/cpu%d/topology/die_id",
38162306a36Sopenharmony_ci			cpu);
38262306a36Sopenharmony_ci	if (ret < 0) {
38362306a36Sopenharmony_ci		int core_id, pkg_id, die_id;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci		ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
38662306a36Sopenharmony_ci		if (!ret) {
38762306a36Sopenharmony_ci			if (die_id < 0)
38862306a36Sopenharmony_ci				die_id = 0;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci			return die_id;
39162306a36Sopenharmony_ci		}
39262306a36Sopenharmony_ci	}
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	if (ret < 0)
39562306a36Sopenharmony_ci		ret = 0;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	return ret;
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_cistatic int get_physical_punit_id(int cpu)
40162306a36Sopenharmony_ci{
40262306a36Sopenharmony_ci	if (cpu < 0)
40362306a36Sopenharmony_ci		return -1;
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	if (cpu_map && cpu_map[cpu].initialized)
40662306a36Sopenharmony_ci		return cpu_map[cpu].punit_id;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	return -1;
40962306a36Sopenharmony_ci}
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_civoid set_isst_id(struct isst_id *id, int cpu)
41262306a36Sopenharmony_ci{
41362306a36Sopenharmony_ci	id->cpu = cpu;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	id->pkg = get_physical_package_id(cpu);
41662306a36Sopenharmony_ci	if (id->pkg >= MAX_PACKAGE_COUNT)
41762306a36Sopenharmony_ci		id->pkg = -1;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	id->die = get_physical_die_id(cpu);
42062306a36Sopenharmony_ci	if (id->die >= MAX_DIE_PER_PACKAGE)
42162306a36Sopenharmony_ci		id->die = -1;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	id->punit = get_physical_punit_id(cpu);
42462306a36Sopenharmony_ci	if (id->punit >= MAX_PUNIT_PER_DIE)
42562306a36Sopenharmony_ci		id->punit = -1;
42662306a36Sopenharmony_ci}
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ciint is_cpu_in_power_domain(int cpu, struct isst_id *id)
42962306a36Sopenharmony_ci{
43062306a36Sopenharmony_ci	struct isst_id tid;
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	set_isst_id(&tid, cpu);
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	if (id->pkg == tid.pkg && id->die == tid.die && id->punit == tid.punit)
43562306a36Sopenharmony_ci		return 1;
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	return 0;
43862306a36Sopenharmony_ci}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ciint get_cpufreq_base_freq(int cpu)
44162306a36Sopenharmony_ci{
44262306a36Sopenharmony_ci	return parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", cpu);
44362306a36Sopenharmony_ci}
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ciint get_topo_max_cpus(void)
44662306a36Sopenharmony_ci{
44762306a36Sopenharmony_ci	return topo_max_cpus;
44862306a36Sopenharmony_ci}
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_cistatic unsigned int is_cpu_online(int cpu)
45162306a36Sopenharmony_ci{
45262306a36Sopenharmony_ci	char buffer[128];
45362306a36Sopenharmony_ci	int fd, ret;
45462306a36Sopenharmony_ci	unsigned char online;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	snprintf(buffer, sizeof(buffer),
45762306a36Sopenharmony_ci		 "/sys/devices/system/cpu/cpu%d/online", cpu);
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	fd = open(buffer, O_RDONLY);
46062306a36Sopenharmony_ci	if (fd < 0)
46162306a36Sopenharmony_ci		return fd;
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	ret = read(fd, &online, sizeof(online));
46462306a36Sopenharmony_ci	close(fd);
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	if (ret == -1)
46762306a36Sopenharmony_ci		return ret;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	if (online == '1')
47062306a36Sopenharmony_ci		online = 1;
47162306a36Sopenharmony_ci	else
47262306a36Sopenharmony_ci		online = 0;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	return online;
47562306a36Sopenharmony_ci}
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_cistatic int get_kernel_version(int *major, int *minor)
47862306a36Sopenharmony_ci{
47962306a36Sopenharmony_ci	struct utsname buf;
48062306a36Sopenharmony_ci	int ret;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	ret = uname(&buf);
48362306a36Sopenharmony_ci	if (ret)
48462306a36Sopenharmony_ci		return ret;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	ret = sscanf(buf.release, "%d.%d", major, minor);
48762306a36Sopenharmony_ci	if (ret != 2)
48862306a36Sopenharmony_ci		return ret;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	return 0;
49162306a36Sopenharmony_ci}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci#define CPU0_HOTPLUG_DEPRECATE_MAJOR_VER	6
49462306a36Sopenharmony_ci#define CPU0_HOTPLUG_DEPRECATE_MINOR_VER	5
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_civoid set_cpu_online_offline(int cpu, int state)
49762306a36Sopenharmony_ci{
49862306a36Sopenharmony_ci	char buffer[128];
49962306a36Sopenharmony_ci	int fd, ret;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	if (!cpu) {
50262306a36Sopenharmony_ci		int major, minor;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci		ret = get_kernel_version(&major, &minor);
50562306a36Sopenharmony_ci		if (!ret) {
50662306a36Sopenharmony_ci			if (major > CPU0_HOTPLUG_DEPRECATE_MAJOR_VER || (major == CPU0_HOTPLUG_DEPRECATE_MAJOR_VER &&
50762306a36Sopenharmony_ci				minor >= CPU0_HOTPLUG_DEPRECATE_MINOR_VER)) {
50862306a36Sopenharmony_ci				debug_printf("Ignore CPU 0 offline/online for kernel version >= %d.%d\n", major, minor);
50962306a36Sopenharmony_ci				debug_printf("Use cgroups to isolate CPU 0\n");
51062306a36Sopenharmony_ci				return;
51162306a36Sopenharmony_ci			}
51262306a36Sopenharmony_ci		}
51362306a36Sopenharmony_ci	}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	snprintf(buffer, sizeof(buffer),
51662306a36Sopenharmony_ci		 "/sys/devices/system/cpu/cpu%d/online", cpu);
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	fd = open(buffer, O_WRONLY);
51962306a36Sopenharmony_ci	if (fd < 0) {
52062306a36Sopenharmony_ci		if (!cpu && state) {
52162306a36Sopenharmony_ci			fprintf(stderr, "This system is not configured for CPU 0 online/offline\n");
52262306a36Sopenharmony_ci			fprintf(stderr, "Ignoring online request for CPU 0 as this is already online\n");
52362306a36Sopenharmony_ci			return;
52462306a36Sopenharmony_ci		}
52562306a36Sopenharmony_ci		err(-1, "%s open failed", buffer);
52662306a36Sopenharmony_ci	}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	if (state)
52962306a36Sopenharmony_ci		ret = write(fd, "1\n", 2);
53062306a36Sopenharmony_ci	else
53162306a36Sopenharmony_ci		ret = write(fd, "0\n", 2);
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	if (ret == -1)
53462306a36Sopenharmony_ci		perror("Online/Offline: Operation failed\n");
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	close(fd);
53762306a36Sopenharmony_ci}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_cistatic void force_all_cpus_online(void)
54062306a36Sopenharmony_ci{
54162306a36Sopenharmony_ci	int i;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	fprintf(stderr, "Forcing all CPUs online\n");
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	for (i = 0; i < topo_max_cpus; ++i)
54662306a36Sopenharmony_ci		set_cpu_online_offline(i, 1);
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	unlink("/var/run/isst_cpu_topology.dat");
54962306a36Sopenharmony_ci}
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_civoid for_each_online_power_domain_in_set(void (*callback)(struct isst_id *, void *, void *,
55262306a36Sopenharmony_ci						     void *, void *),
55362306a36Sopenharmony_ci				    void *arg1, void *arg2, void *arg3,
55462306a36Sopenharmony_ci				    void *arg4)
55562306a36Sopenharmony_ci{
55662306a36Sopenharmony_ci	struct isst_id id;
55762306a36Sopenharmony_ci	int cpus[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];
55862306a36Sopenharmony_ci	int valid_mask[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE] = {0};
55962306a36Sopenharmony_ci	int i, j, k;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	memset(cpus, -1, sizeof(cpus));
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	for (i = 0; i < topo_max_cpus; ++i) {
56462306a36Sopenharmony_ci		int online;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci		if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
56762306a36Sopenharmony_ci			continue;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci		online = parse_int_file(
57062306a36Sopenharmony_ci			i != 0, "/sys/devices/system/cpu/cpu%d/online", i);
57162306a36Sopenharmony_ci		if (online < 0)
57262306a36Sopenharmony_ci			online = 1; /* online entry for CPU 0 needs some special configs */
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci		if (!online)
57562306a36Sopenharmony_ci			continue;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci		set_isst_id(&id, i);
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci		if (id.pkg < 0 || id.die < 0 || id.punit < 0)
58062306a36Sopenharmony_ci			continue;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci		valid_mask[id.pkg][id.die] = 1;
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci		if (cpus[id.pkg][id.die][id.punit] == -1)
58562306a36Sopenharmony_ci			cpus[id.pkg][id.die][id.punit] = i;
58662306a36Sopenharmony_ci	}
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	for (i = 0; i < MAX_PACKAGE_COUNT; i++) {
58962306a36Sopenharmony_ci		for (j = 0; j < MAX_DIE_PER_PACKAGE; j++) {
59062306a36Sopenharmony_ci			/*
59162306a36Sopenharmony_ci			 * Fix me:
59262306a36Sopenharmony_ci			 * How to check a non-cpu die for a package/die with all cpu offlined?
59362306a36Sopenharmony_ci			 */
59462306a36Sopenharmony_ci			if (!valid_mask[i][j])
59562306a36Sopenharmony_ci				continue;
59662306a36Sopenharmony_ci			for (k = 0; k < MAX_PUNIT_PER_DIE; k++) {
59762306a36Sopenharmony_ci				id.cpu = cpus[i][j][k];
59862306a36Sopenharmony_ci				id.pkg = i;
59962306a36Sopenharmony_ci				id.die = j;
60062306a36Sopenharmony_ci				id.punit = k;
60162306a36Sopenharmony_ci				if (isst_is_punit_valid(&id))
60262306a36Sopenharmony_ci					callback(&id, arg1, arg2, arg3, arg4);
60362306a36Sopenharmony_ci			}
60462306a36Sopenharmony_ci		}
60562306a36Sopenharmony_ci	}
60662306a36Sopenharmony_ci}
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_cistatic void for_each_online_target_cpu_in_set(
60962306a36Sopenharmony_ci	void (*callback)(struct isst_id *, void *, void *, void *, void *), void *arg1,
61062306a36Sopenharmony_ci	void *arg2, void *arg3, void *arg4)
61162306a36Sopenharmony_ci{
61262306a36Sopenharmony_ci	int i, found = 0;
61362306a36Sopenharmony_ci	struct isst_id id;
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	for (i = 0; i < topo_max_cpus; ++i) {
61662306a36Sopenharmony_ci		int online;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci		if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
61962306a36Sopenharmony_ci			continue;
62062306a36Sopenharmony_ci		if (i)
62162306a36Sopenharmony_ci			online = parse_int_file(
62262306a36Sopenharmony_ci				1, "/sys/devices/system/cpu/cpu%d/online", i);
62362306a36Sopenharmony_ci		else
62462306a36Sopenharmony_ci			online =
62562306a36Sopenharmony_ci				1; /* online entry for CPU 0 needs some special configs */
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci		set_isst_id(&id, i);
62862306a36Sopenharmony_ci		if (online && callback) {
62962306a36Sopenharmony_ci			callback(&id, arg1, arg2, arg3, arg4);
63062306a36Sopenharmony_ci			found = 1;
63162306a36Sopenharmony_ci		}
63262306a36Sopenharmony_ci	}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	if (!found)
63562306a36Sopenharmony_ci		fprintf(stderr, "No valid CPU in the list\n");
63662306a36Sopenharmony_ci}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci#define BITMASK_SIZE 32
63962306a36Sopenharmony_cistatic void set_max_cpu_num(void)
64062306a36Sopenharmony_ci{
64162306a36Sopenharmony_ci	FILE *filep;
64262306a36Sopenharmony_ci	unsigned long dummy;
64362306a36Sopenharmony_ci	int i;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	topo_max_cpus = 0;
64662306a36Sopenharmony_ci	for (i = 0; i < 256; ++i) {
64762306a36Sopenharmony_ci		char path[256];
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci		snprintf(path, sizeof(path),
65062306a36Sopenharmony_ci			 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i);
65162306a36Sopenharmony_ci		filep = fopen(path, "r");
65262306a36Sopenharmony_ci		if (filep)
65362306a36Sopenharmony_ci			break;
65462306a36Sopenharmony_ci	}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	if (!filep) {
65762306a36Sopenharmony_ci		fprintf(stderr, "Can't get max cpu number\n");
65862306a36Sopenharmony_ci		exit(0);
65962306a36Sopenharmony_ci	}
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	while (fscanf(filep, "%lx,", &dummy) == 1)
66262306a36Sopenharmony_ci		topo_max_cpus += BITMASK_SIZE;
66362306a36Sopenharmony_ci	fclose(filep);
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	debug_printf("max cpus %d\n", topo_max_cpus);
66662306a36Sopenharmony_ci}
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_cisize_t alloc_cpu_set(cpu_set_t **cpu_set)
66962306a36Sopenharmony_ci{
67062306a36Sopenharmony_ci	cpu_set_t *_cpu_set;
67162306a36Sopenharmony_ci	size_t size;
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	_cpu_set = CPU_ALLOC((topo_max_cpus + 1));
67462306a36Sopenharmony_ci	if (_cpu_set == NULL)
67562306a36Sopenharmony_ci		err(3, "CPU_ALLOC");
67662306a36Sopenharmony_ci	size = CPU_ALLOC_SIZE((topo_max_cpus + 1));
67762306a36Sopenharmony_ci	CPU_ZERO_S(size, _cpu_set);
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	*cpu_set = _cpu_set;
68062306a36Sopenharmony_ci	return size;
68162306a36Sopenharmony_ci}
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_civoid free_cpu_set(cpu_set_t *cpu_set)
68462306a36Sopenharmony_ci{
68562306a36Sopenharmony_ci	CPU_FREE(cpu_set);
68662306a36Sopenharmony_ci}
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_cistatic int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ciint get_max_punit_core_id(struct isst_id *id)
69162306a36Sopenharmony_ci{
69262306a36Sopenharmony_ci	int max_id = 0;
69362306a36Sopenharmony_ci	int i;
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	for (i = 0; i < topo_max_cpus; ++i)
69662306a36Sopenharmony_ci	{
69762306a36Sopenharmony_ci		if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
69862306a36Sopenharmony_ci			continue;
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci		if (is_cpu_in_power_domain(i, id) &&
70162306a36Sopenharmony_ci		    cpu_map[i].punit_cpu_core > max_id)
70262306a36Sopenharmony_ci			max_id = cpu_map[i].punit_cpu_core;
70362306a36Sopenharmony_ci	}
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci	return max_id;
70662306a36Sopenharmony_ci}
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ciint get_cpu_count(struct isst_id *id)
70962306a36Sopenharmony_ci{
71062306a36Sopenharmony_ci	if (id->pkg < 0 || id->die < 0 || id->punit < 0)
71162306a36Sopenharmony_ci		return 0;
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	return cpu_cnt[id->pkg][id->die][id->punit];
71462306a36Sopenharmony_ci}
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_cistatic void update_punit_cpu_info(__u32 physical_cpu, struct _cpu_map *cpu_map)
71762306a36Sopenharmony_ci{
71862306a36Sopenharmony_ci	if (api_version() > 1) {
71962306a36Sopenharmony_ci		/*
72062306a36Sopenharmony_ci		 * MSR 0x54 format
72162306a36Sopenharmony_ci		 *	[15:11] PM_DOMAIN_ID
72262306a36Sopenharmony_ci		 *	[10:3] MODULE_ID (aka IDI_AGENT_ID)
72362306a36Sopenharmony_ci		 *	[2:0] LP_ID (We don't care about these bits we only
72462306a36Sopenharmony_ci		 *		care die and core id
72562306a36Sopenharmony_ci		 *	For Atom:
72662306a36Sopenharmony_ci		 *	[2] Always 0
72762306a36Sopenharmony_ci		 *	[1:0] core ID within module
72862306a36Sopenharmony_ci		 *	For Core
72962306a36Sopenharmony_ci		 *	[2:1] Always 0
73062306a36Sopenharmony_ci		 *	[0] thread ID
73162306a36Sopenharmony_ci		 */
73262306a36Sopenharmony_ci		cpu_map->punit_id = (physical_cpu >> 11) & 0x1f;
73362306a36Sopenharmony_ci		cpu_map->punit_cpu_core = (physical_cpu >> 3) & 0xff;
73462306a36Sopenharmony_ci		cpu_map->punit_cpu = physical_cpu & 0x7ff;
73562306a36Sopenharmony_ci	} else {
73662306a36Sopenharmony_ci		int punit_id;
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci		/*
73962306a36Sopenharmony_ci		 * MSR 0x53 format
74062306a36Sopenharmony_ci		 * Format
74162306a36Sopenharmony_ci		 *      Bit 0 – thread ID
74262306a36Sopenharmony_ci		 *      Bit 8:1 – core ID
74362306a36Sopenharmony_ci		 *      Bit 13:9 – punit ID
74462306a36Sopenharmony_ci		 */
74562306a36Sopenharmony_ci		cpu_map->punit_cpu = physical_cpu & 0x1ff;
74662306a36Sopenharmony_ci		cpu_map->punit_cpu_core = (cpu_map->punit_cpu >> 1); // shift to get core id
74762306a36Sopenharmony_ci		punit_id = (physical_cpu >> 9) & 0x1f;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci		if (punit_id >= MAX_PUNIT_PER_DIE)
75062306a36Sopenharmony_ci			punit_id = 0;
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci		cpu_map->punit_id = punit_id;
75362306a36Sopenharmony_ci	}
75462306a36Sopenharmony_ci}
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_cistatic void create_cpu_map(void)
75762306a36Sopenharmony_ci{
75862306a36Sopenharmony_ci	const char *pathname = "/dev/isst_interface";
75962306a36Sopenharmony_ci	size_t size;
76062306a36Sopenharmony_ci	DIR *dir;
76162306a36Sopenharmony_ci	int i, fd = 0;
76262306a36Sopenharmony_ci	struct isst_if_cpu_maps map;
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci	/* Use calloc to make sure the memory is initialized to Zero */
76562306a36Sopenharmony_ci	cpu_map = calloc(topo_max_cpus, sizeof(*cpu_map));
76662306a36Sopenharmony_ci	if (!cpu_map)
76762306a36Sopenharmony_ci		err(3, "cpumap");
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	fd = open(pathname, O_RDWR);
77062306a36Sopenharmony_ci	if (fd < 0 && !is_clx_n_platform())
77162306a36Sopenharmony_ci		err(-1, "%s open failed", pathname);
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	size = alloc_cpu_set(&present_cpumask);
77462306a36Sopenharmony_ci	present_cpumask_size = size;
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	for (i = 0; i < topo_max_cpus; ++i) {
77762306a36Sopenharmony_ci		char buffer[256];
77862306a36Sopenharmony_ci		int pkg_id, die_id, core_id, punit_id;
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_ci		/* check if CPU is online */
78162306a36Sopenharmony_ci		snprintf(buffer, sizeof(buffer),
78262306a36Sopenharmony_ci			 "/sys/devices/system/cpu/cpu%d", i);
78362306a36Sopenharmony_ci		dir = opendir(buffer);
78462306a36Sopenharmony_ci		if (!dir)
78562306a36Sopenharmony_ci			continue;
78662306a36Sopenharmony_ci		closedir(dir);
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci		CPU_SET_S(i, size, present_cpumask);
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci		pkg_id = get_physical_package_id(i);
79162306a36Sopenharmony_ci		die_id = get_physical_die_id(i);
79262306a36Sopenharmony_ci		core_id = get_physical_core_id(i);
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci		if (pkg_id < 0 || die_id < 0 || core_id < 0)
79562306a36Sopenharmony_ci			continue;
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci		cpu_map[i].pkg_id = pkg_id;
79862306a36Sopenharmony_ci		cpu_map[i].die_id = die_id;
79962306a36Sopenharmony_ci		cpu_map[i].core_id = core_id;
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci		punit_id = 0;
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci		if (fd >= 0) {
80562306a36Sopenharmony_ci			map.cmd_count = 1;
80662306a36Sopenharmony_ci			map.cpu_map[0].logical_cpu = i;
80762306a36Sopenharmony_ci			debug_printf(" map logical_cpu:%d\n",
80862306a36Sopenharmony_ci				     map.cpu_map[0].logical_cpu);
80962306a36Sopenharmony_ci			if (ioctl(fd, ISST_IF_GET_PHY_ID, &map) == -1) {
81062306a36Sopenharmony_ci				perror("ISST_IF_GET_PHY_ID");
81162306a36Sopenharmony_ci				fprintf(outf, "Error: map logical_cpu:%d\n",
81262306a36Sopenharmony_ci					map.cpu_map[0].logical_cpu);
81362306a36Sopenharmony_ci			} else {
81462306a36Sopenharmony_ci				update_punit_cpu_info(map.cpu_map[0].physical_cpu, &cpu_map[i]);
81562306a36Sopenharmony_ci				punit_id = cpu_map[i].punit_id;
81662306a36Sopenharmony_ci			}
81762306a36Sopenharmony_ci		}
81862306a36Sopenharmony_ci		cpu_map[i].initialized = 1;
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci		cpu_cnt[pkg_id][die_id][punit_id]++;
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci		debug_printf(
82362306a36Sopenharmony_ci			"map logical_cpu:%d core: %d die:%d pkg:%d punit:%d punit_cpu:%d punit_core:%d\n",
82462306a36Sopenharmony_ci			i, cpu_map[i].core_id, cpu_map[i].die_id,
82562306a36Sopenharmony_ci			cpu_map[i].pkg_id, cpu_map[i].punit_id,
82662306a36Sopenharmony_ci			cpu_map[i].punit_cpu, cpu_map[i].punit_cpu_core);
82762306a36Sopenharmony_ci	}
82862306a36Sopenharmony_ci	if (fd >= 0)
82962306a36Sopenharmony_ci		close(fd);
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_ci	size = alloc_cpu_set(&target_cpumask);
83262306a36Sopenharmony_ci	target_cpumask_size = size;
83362306a36Sopenharmony_ci	for (i = 0; i < max_target_cpus; ++i) {
83462306a36Sopenharmony_ci		if (!CPU_ISSET_S(target_cpus[i], present_cpumask_size,
83562306a36Sopenharmony_ci				 present_cpumask))
83662306a36Sopenharmony_ci			continue;
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci		CPU_SET_S(target_cpus[i], size, target_cpumask);
83962306a36Sopenharmony_ci	}
84062306a36Sopenharmony_ci}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_civoid set_cpu_mask_from_punit_coremask(struct isst_id *id, unsigned long long core_mask,
84362306a36Sopenharmony_ci				      size_t core_cpumask_size,
84462306a36Sopenharmony_ci				      cpu_set_t *core_cpumask, int *cpu_cnt)
84562306a36Sopenharmony_ci{
84662306a36Sopenharmony_ci	int i, cnt = 0;
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	if (id->cpu < 0)
84962306a36Sopenharmony_ci		return;
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	*cpu_cnt = 0;
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	for (i = 0; i < 64; ++i) {
85462306a36Sopenharmony_ci		if (core_mask & BIT_ULL(i)) {
85562306a36Sopenharmony_ci			int j;
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci			for (j = 0; j < topo_max_cpus; ++j) {
85862306a36Sopenharmony_ci				if (!CPU_ISSET_S(j, present_cpumask_size, present_cpumask))
85962306a36Sopenharmony_ci					continue;
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci				if (is_cpu_in_power_domain(j, id) &&
86262306a36Sopenharmony_ci				    cpu_map[j].punit_cpu_core == i) {
86362306a36Sopenharmony_ci					CPU_SET_S(j, core_cpumask_size,
86462306a36Sopenharmony_ci						  core_cpumask);
86562306a36Sopenharmony_ci					++cnt;
86662306a36Sopenharmony_ci				}
86762306a36Sopenharmony_ci			}
86862306a36Sopenharmony_ci		}
86962306a36Sopenharmony_ci	}
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	*cpu_cnt = cnt;
87262306a36Sopenharmony_ci}
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ciint find_phy_core_num(int logical_cpu)
87562306a36Sopenharmony_ci{
87662306a36Sopenharmony_ci	if (logical_cpu < topo_max_cpus)
87762306a36Sopenharmony_ci		return cpu_map[logical_cpu].punit_cpu_core;
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	return -EINVAL;
88062306a36Sopenharmony_ci}
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ciint use_cgroupv2(void)
88362306a36Sopenharmony_ci{
88462306a36Sopenharmony_ci	return cgroupv2;
88562306a36Sopenharmony_ci}
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ciint enable_cpuset_controller(void)
88862306a36Sopenharmony_ci{
88962306a36Sopenharmony_ci	int fd, ret;
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	fd = open("/sys/fs/cgroup/cgroup.subtree_control", O_RDWR, 0);
89262306a36Sopenharmony_ci	if (fd < 0) {
89362306a36Sopenharmony_ci		debug_printf("Can't activate cpuset controller\n");
89462306a36Sopenharmony_ci		debug_printf("Either you are not root user or CGroup v2 is not supported\n");
89562306a36Sopenharmony_ci		return fd;
89662306a36Sopenharmony_ci	}
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	ret = write(fd, " +cpuset", strlen(" +cpuset"));
89962306a36Sopenharmony_ci	close(fd);
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	if (ret == -1) {
90262306a36Sopenharmony_ci		debug_printf("Can't activate cpuset controller: Write failed\n");
90362306a36Sopenharmony_ci		return ret;
90462306a36Sopenharmony_ci	}
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	return 0;
90762306a36Sopenharmony_ci}
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ciint isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int level)
91062306a36Sopenharmony_ci{
91162306a36Sopenharmony_ci	int i, first, curr_index, index, ret, fd;
91262306a36Sopenharmony_ci	static char str[512], dir_name[64];
91362306a36Sopenharmony_ci	static char cpuset_cpus[128];
91462306a36Sopenharmony_ci	int str_len = sizeof(str);
91562306a36Sopenharmony_ci	DIR *dir;
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	snprintf(dir_name, sizeof(dir_name), "/sys/fs/cgroup/%d-%d-%d", id->pkg, id->die, id->punit);
91862306a36Sopenharmony_ci	dir = opendir(dir_name);
91962306a36Sopenharmony_ci	if (!dir) {
92062306a36Sopenharmony_ci		ret = mkdir(dir_name, 0744);
92162306a36Sopenharmony_ci		if (ret) {
92262306a36Sopenharmony_ci			debug_printf("Can't create dir:%s errno:%d\n", dir_name, errno);
92362306a36Sopenharmony_ci			return ret;
92462306a36Sopenharmony_ci		}
92562306a36Sopenharmony_ci	}
92662306a36Sopenharmony_ci	closedir(dir);
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	if (!level) {
92962306a36Sopenharmony_ci		sprintf(cpuset_cpus, "%s/cpuset.cpus.partition", dir_name);
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci		fd = open(cpuset_cpus, O_RDWR, 0);
93262306a36Sopenharmony_ci		if (fd < 0) {
93362306a36Sopenharmony_ci			return fd;
93462306a36Sopenharmony_ci		}
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci		ret = write(fd, "member", strlen("member"));
93762306a36Sopenharmony_ci		if (ret == -1) {
93862306a36Sopenharmony_ci			printf("Can't update to member\n");
93962306a36Sopenharmony_ci			return ret;
94062306a36Sopenharmony_ci		}
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci		return 0;
94362306a36Sopenharmony_ci	}
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci	if (!CPU_COUNT_S(mask_size, cpu_mask)) {
94662306a36Sopenharmony_ci		return -1;
94762306a36Sopenharmony_ci	}
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci	curr_index = 0;
95062306a36Sopenharmony_ci	first = 1;
95162306a36Sopenharmony_ci	str[0] = '\0';
95262306a36Sopenharmony_ci	for (i = 0; i < get_topo_max_cpus(); ++i) {
95362306a36Sopenharmony_ci		if (!is_cpu_in_power_domain(i, id))
95462306a36Sopenharmony_ci			continue;
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci		if (CPU_ISSET_S(i, mask_size, cpu_mask))
95762306a36Sopenharmony_ci			continue;
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci		if (!first) {
96062306a36Sopenharmony_ci			index = snprintf(&str[curr_index],
96162306a36Sopenharmony_ci					 str_len - curr_index, ",");
96262306a36Sopenharmony_ci			curr_index += index;
96362306a36Sopenharmony_ci			if (curr_index >= str_len)
96462306a36Sopenharmony_ci				break;
96562306a36Sopenharmony_ci		}
96662306a36Sopenharmony_ci		index = snprintf(&str[curr_index], str_len - curr_index, "%d",
96762306a36Sopenharmony_ci				 i);
96862306a36Sopenharmony_ci		curr_index += index;
96962306a36Sopenharmony_ci		if (curr_index >= str_len)
97062306a36Sopenharmony_ci			break;
97162306a36Sopenharmony_ci		first = 0;
97262306a36Sopenharmony_ci	}
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	debug_printf("isolated CPUs list: package:%d curr_index:%d [%s]\n", id->pkg, curr_index ,str);
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	snprintf(cpuset_cpus, sizeof(cpuset_cpus), "%s/cpuset.cpus", dir_name);
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	fd = open(cpuset_cpus, O_RDWR, 0);
97962306a36Sopenharmony_ci	if (fd < 0) {
98062306a36Sopenharmony_ci		return fd;
98162306a36Sopenharmony_ci	}
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci	ret = write(fd, str, strlen(str));
98462306a36Sopenharmony_ci	close(fd);
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	if (ret == -1) {
98762306a36Sopenharmony_ci		debug_printf("Can't activate cpuset controller: Write failed\n");
98862306a36Sopenharmony_ci		return ret;
98962306a36Sopenharmony_ci	}
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	snprintf(cpuset_cpus, sizeof(cpuset_cpus), "%s/cpuset.cpus.partition", dir_name);
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	fd = open(cpuset_cpus, O_RDWR, 0);
99462306a36Sopenharmony_ci	if (fd < 0) {
99562306a36Sopenharmony_ci		return fd;
99662306a36Sopenharmony_ci	}
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	ret = write(fd, "isolated", strlen("isolated"));
99962306a36Sopenharmony_ci	if (ret == -1) {
100062306a36Sopenharmony_ci		debug_printf("Can't update to isolated\n");
100162306a36Sopenharmony_ci		ret = write(fd, "root", strlen("root"));
100262306a36Sopenharmony_ci		if (ret == -1)
100362306a36Sopenharmony_ci			debug_printf("Can't update to root\n");
100462306a36Sopenharmony_ci	}
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	close(fd);
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	if (ret < 0)
100962306a36Sopenharmony_ci		return ret;
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	return 0;
101262306a36Sopenharmony_ci}
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_cistatic int isst_fill_platform_info(void)
101562306a36Sopenharmony_ci{
101662306a36Sopenharmony_ci	const char *pathname = "/dev/isst_interface";
101762306a36Sopenharmony_ci	int fd;
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	if (is_clx_n_platform()) {
102062306a36Sopenharmony_ci		isst_platform_info.api_version = 1;
102162306a36Sopenharmony_ci		goto set_platform_ops;
102262306a36Sopenharmony_ci	}
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci	fd = open(pathname, O_RDWR);
102562306a36Sopenharmony_ci	if (fd < 0)
102662306a36Sopenharmony_ci		err(-1, "%s open failed", pathname);
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &isst_platform_info) == -1) {
102962306a36Sopenharmony_ci		perror("ISST_IF_GET_PLATFORM_INFO");
103062306a36Sopenharmony_ci		close(fd);
103162306a36Sopenharmony_ci		return -1;
103262306a36Sopenharmony_ci	}
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci	close(fd);
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci	if (isst_platform_info.api_version > supported_api_ver) {
103762306a36Sopenharmony_ci		printf("Incompatible API versions; Upgrade of tool is required\n");
103862306a36Sopenharmony_ci		return -1;
103962306a36Sopenharmony_ci	}
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ciset_platform_ops:
104262306a36Sopenharmony_ci	if (isst_set_platform_ops(isst_platform_info.api_version)) {
104362306a36Sopenharmony_ci		fprintf(stderr, "Failed to set platform callbacks\n");
104462306a36Sopenharmony_ci		exit(0);
104562306a36Sopenharmony_ci	}
104662306a36Sopenharmony_ci	return 0;
104762306a36Sopenharmony_ci}
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_civoid get_isst_status(struct isst_id *id, void *arg1, void *arg2, void *arg3, void *arg4)
105062306a36Sopenharmony_ci{
105162306a36Sopenharmony_ci	struct isst_pkg_ctdp pkg_dev;
105262306a36Sopenharmony_ci	struct isst_id *tid = (struct isst_id *)arg2;
105362306a36Sopenharmony_ci	int *mask = (int *)arg3;
105462306a36Sopenharmony_ci	int *max_level = (int *)arg4;
105562306a36Sopenharmony_ci	int j, ret;
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci	/* Only check the first cpu power domain */
105862306a36Sopenharmony_ci	if (id->cpu < 0 || tid->cpu >= 0)
105962306a36Sopenharmony_ci		return;
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci	ret = isst_get_ctdp_levels(id, &pkg_dev);
106262306a36Sopenharmony_ci	if (ret)
106362306a36Sopenharmony_ci		return;
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	if (pkg_dev.enabled)
106662306a36Sopenharmony_ci		*mask |= BIT(0);
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci	if (pkg_dev.locked)
106962306a36Sopenharmony_ci		*mask |= BIT(1);
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	if (*max_level < pkg_dev.levels)
107262306a36Sopenharmony_ci		*max_level = pkg_dev.levels;
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci	for (j = 0; j <= pkg_dev.levels; ++j) {
107562306a36Sopenharmony_ci		struct isst_pkg_ctdp_level_info ctdp_level;
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci		ret = isst_get_ctdp_control(id, j, &ctdp_level);
107862306a36Sopenharmony_ci		if (ret)
107962306a36Sopenharmony_ci			continue;
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci		if (ctdp_level.fact_support)
108262306a36Sopenharmony_ci			*mask |= BIT(2);
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci		if (ctdp_level.pbf_support)
108562306a36Sopenharmony_ci			*mask |= BIT(3);
108662306a36Sopenharmony_ci	}
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	tid->cpu = id->cpu;
108962306a36Sopenharmony_ci	tid->pkg = id->pkg;
109062306a36Sopenharmony_ci	tid->die = id->die;
109162306a36Sopenharmony_ci	tid->punit = id->punit;
109262306a36Sopenharmony_ci}
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_cistatic void isst_print_extended_platform_info(void)
109562306a36Sopenharmony_ci{
109662306a36Sopenharmony_ci	int cp_state, cp_cap;
109762306a36Sopenharmony_ci	struct isst_id id;
109862306a36Sopenharmony_ci	int mask = 0, max_level = 0;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	id.cpu = -1;
110162306a36Sopenharmony_ci	for_each_online_power_domain_in_set(get_isst_status, NULL, &id, &mask, &max_level);
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci	if (mask & BIT(0)) {
110462306a36Sopenharmony_ci		fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is supported\n");
110562306a36Sopenharmony_ci	} else {
110662306a36Sopenharmony_ci		fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is not supported\n");
110762306a36Sopenharmony_ci		fprintf(outf, "Only performance level 0 (base level) is present\n");
110862306a36Sopenharmony_ci	}
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	if (mask & BIT(1))
111162306a36Sopenharmony_ci		fprintf(outf, "TDP level change control is locked\n");
111262306a36Sopenharmony_ci	else
111362306a36Sopenharmony_ci		fprintf(outf, "TDP level change control is unlocked, max level: %d\n", max_level);
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	if (mask & BIT(2))
111662306a36Sopenharmony_ci		fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is supported\n");
111762306a36Sopenharmony_ci	else
111862306a36Sopenharmony_ci		fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is not supported\n");
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	if (mask & BIT(3))
112162306a36Sopenharmony_ci		fprintf(outf, "Intel(R) SST-BF (feature base-freq) is supported\n");
112262306a36Sopenharmony_ci	else
112362306a36Sopenharmony_ci		fprintf(outf, "Intel(R) SST-BF (feature base-freq) is not supported\n");
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci	if (isst_read_pm_config(&id, &cp_state, &cp_cap)) {
112662306a36Sopenharmony_ci		fprintf(outf, "Intel(R) SST-CP (feature core-power) status is unknown\n");
112762306a36Sopenharmony_ci		return;
112862306a36Sopenharmony_ci	}
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	if (cp_cap)
113162306a36Sopenharmony_ci		fprintf(outf, "Intel(R) SST-CP (feature core-power) is supported\n");
113262306a36Sopenharmony_ci	else
113362306a36Sopenharmony_ci		fprintf(outf, "Intel(R) SST-CP (feature core-power) is not supported\n");
113462306a36Sopenharmony_ci}
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_cistatic void isst_print_platform_information(void)
113762306a36Sopenharmony_ci{
113862306a36Sopenharmony_ci	if (is_clx_n_platform()) {
113962306a36Sopenharmony_ci		fprintf(stderr, "\nThis option in not supported on this platform\n");
114062306a36Sopenharmony_ci		exit(0);
114162306a36Sopenharmony_ci	}
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	/* Early initialization to create working cpu_map */
114462306a36Sopenharmony_ci	set_max_cpu_num();
114562306a36Sopenharmony_ci	create_cpu_map();
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci	fprintf(outf, "Platform: API version : %d\n",
114862306a36Sopenharmony_ci		isst_platform_info.api_version);
114962306a36Sopenharmony_ci	fprintf(outf, "Platform: Driver version : %d\n",
115062306a36Sopenharmony_ci		isst_platform_info.driver_version);
115162306a36Sopenharmony_ci	fprintf(outf, "Platform: mbox supported : %d\n",
115262306a36Sopenharmony_ci		isst_platform_info.mbox_supported);
115362306a36Sopenharmony_ci	fprintf(outf, "Platform: mmio supported : %d\n",
115462306a36Sopenharmony_ci		isst_platform_info.mmio_supported);
115562306a36Sopenharmony_ci	isst_print_extended_platform_info();
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	exit(0);
115862306a36Sopenharmony_ci}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_cistatic char *local_str0, *local_str1;
116162306a36Sopenharmony_cistatic void exec_on_get_ctdp_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
116262306a36Sopenharmony_ci				 void *arg4)
116362306a36Sopenharmony_ci{
116462306a36Sopenharmony_ci	int (*fn_ptr)(struct isst_id *id, void *arg);
116562306a36Sopenharmony_ci	int ret;
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	fn_ptr = arg1;
116862306a36Sopenharmony_ci	ret = fn_ptr(id, arg2);
116962306a36Sopenharmony_ci	if (ret)
117062306a36Sopenharmony_ci		isst_display_error_info_message(1, "get_tdp_* failed", 0, 0);
117162306a36Sopenharmony_ci	else
117262306a36Sopenharmony_ci		isst_ctdp_display_core_info(id, outf, arg3,
117362306a36Sopenharmony_ci					    *(unsigned int *)arg4,
117462306a36Sopenharmony_ci					    local_str0, local_str1);
117562306a36Sopenharmony_ci}
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_ci#define _get_tdp_level(desc, suffix, object, help, str0, str1)			\
117862306a36Sopenharmony_ci	static void get_tdp_##object(int arg)                                    \
117962306a36Sopenharmony_ci	{                                                                         \
118062306a36Sopenharmony_ci		struct isst_pkg_ctdp ctdp;                                        \
118162306a36Sopenharmony_ci\
118262306a36Sopenharmony_ci		if (cmd_help) {                                                   \
118362306a36Sopenharmony_ci			fprintf(stderr,                                           \
118462306a36Sopenharmony_ci				"Print %s [No command arguments are required]\n", \
118562306a36Sopenharmony_ci				help);                                            \
118662306a36Sopenharmony_ci			exit(0);                                                  \
118762306a36Sopenharmony_ci		}                                                                 \
118862306a36Sopenharmony_ci		local_str0 = str0;						  \
118962306a36Sopenharmony_ci		local_str1 = str1;						  \
119062306a36Sopenharmony_ci		isst_ctdp_display_information_start(outf);                        \
119162306a36Sopenharmony_ci		if (max_target_cpus)                                              \
119262306a36Sopenharmony_ci			for_each_online_target_cpu_in_set(                        \
119362306a36Sopenharmony_ci				exec_on_get_ctdp_cpu, isst_get_ctdp_##suffix,     \
119462306a36Sopenharmony_ci				&ctdp, desc, &ctdp.object);                       \
119562306a36Sopenharmony_ci		else                                                              \
119662306a36Sopenharmony_ci			for_each_online_power_domain_in_set(exec_on_get_ctdp_cpu,      \
119762306a36Sopenharmony_ci						       isst_get_ctdp_##suffix,    \
119862306a36Sopenharmony_ci						       &ctdp, desc,               \
119962306a36Sopenharmony_ci						       &ctdp.object);             \
120062306a36Sopenharmony_ci		isst_ctdp_display_information_end(outf);                          \
120162306a36Sopenharmony_ci	}
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci_get_tdp_level("get-config-levels", levels, levels, "Max TDP level", NULL, NULL);
120462306a36Sopenharmony_ci_get_tdp_level("get-config-version", levels, version, "TDP version", NULL, NULL);
120562306a36Sopenharmony_ci_get_tdp_level("get-config-enabled", levels, enabled, "perf-profile enable status", "disabled", "enabled");
120662306a36Sopenharmony_ci_get_tdp_level("get-config-current_level", levels, current_level,
120762306a36Sopenharmony_ci	       "Current TDP Level", NULL, NULL);
120862306a36Sopenharmony_ci_get_tdp_level("get-lock-status", levels, locked, "TDP lock status", "unlocked", "locked");
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_cistruct isst_pkg_ctdp clx_n_pkg_dev;
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_cistatic int clx_n_get_base_ratio(void)
121362306a36Sopenharmony_ci{
121462306a36Sopenharmony_ci	FILE *fp;
121562306a36Sopenharmony_ci	char *begin, *end, *line = NULL;
121662306a36Sopenharmony_ci	char number[5];
121762306a36Sopenharmony_ci	float value = 0;
121862306a36Sopenharmony_ci	size_t n = 0;
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci	fp = fopen("/proc/cpuinfo", "r");
122162306a36Sopenharmony_ci	if (!fp)
122262306a36Sopenharmony_ci		err(-1, "cannot open /proc/cpuinfo\n");
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	while (getline(&line, &n, fp) > 0) {
122562306a36Sopenharmony_ci		if (strstr(line, "model name")) {
122662306a36Sopenharmony_ci			/* this is true for CascadeLake-N */
122762306a36Sopenharmony_ci			begin = strstr(line, "@ ") + 2;
122862306a36Sopenharmony_ci			end = strstr(line, "GHz");
122962306a36Sopenharmony_ci			strncpy(number, begin, end - begin);
123062306a36Sopenharmony_ci			value = atof(number) * 10;
123162306a36Sopenharmony_ci			break;
123262306a36Sopenharmony_ci		}
123362306a36Sopenharmony_ci	}
123462306a36Sopenharmony_ci	free(line);
123562306a36Sopenharmony_ci	fclose(fp);
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	return (int)(value);
123862306a36Sopenharmony_ci}
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_cistatic int clx_n_config(struct isst_id *id)
124162306a36Sopenharmony_ci{
124262306a36Sopenharmony_ci	int i, ret;
124362306a36Sopenharmony_ci	unsigned long cpu_bf;
124462306a36Sopenharmony_ci	struct isst_pkg_ctdp_level_info *ctdp_level;
124562306a36Sopenharmony_ci	struct isst_pbf_info *pbf_info;
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci	ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
124862306a36Sopenharmony_ci	pbf_info = &ctdp_level->pbf_info;
124962306a36Sopenharmony_ci	ctdp_level->core_cpumask_size =
125062306a36Sopenharmony_ci			alloc_cpu_set(&ctdp_level->core_cpumask);
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_ci	/* find the frequency base ratio */
125362306a36Sopenharmony_ci	ctdp_level->tdp_ratio = clx_n_get_base_ratio();
125462306a36Sopenharmony_ci	if (ctdp_level->tdp_ratio == 0) {
125562306a36Sopenharmony_ci		debug_printf("CLX: cn base ratio is zero\n");
125662306a36Sopenharmony_ci		ret = -1;
125762306a36Sopenharmony_ci		goto error_ret;
125862306a36Sopenharmony_ci	}
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_ci	/* find the high and low priority frequencies */
126162306a36Sopenharmony_ci	pbf_info->p1_high = 0;
126262306a36Sopenharmony_ci	pbf_info->p1_low = ~0;
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci	for (i = 0; i < topo_max_cpus; i++) {
126562306a36Sopenharmony_ci		if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
126662306a36Sopenharmony_ci			continue;
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci		if (!is_cpu_in_power_domain(i, id))
126962306a36Sopenharmony_ci			continue;
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_ci		CPU_SET_S(i, ctdp_level->core_cpumask_size,
127262306a36Sopenharmony_ci			  ctdp_level->core_cpumask);
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci		cpu_bf = parse_int_file(1,
127562306a36Sopenharmony_ci			"/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency",
127662306a36Sopenharmony_ci					i);
127762306a36Sopenharmony_ci		if (cpu_bf > pbf_info->p1_high)
127862306a36Sopenharmony_ci			pbf_info->p1_high = cpu_bf;
127962306a36Sopenharmony_ci		if (cpu_bf < pbf_info->p1_low)
128062306a36Sopenharmony_ci			pbf_info->p1_low = cpu_bf;
128162306a36Sopenharmony_ci	}
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	if (pbf_info->p1_high == ~0UL) {
128462306a36Sopenharmony_ci		debug_printf("CLX: maximum base frequency not set\n");
128562306a36Sopenharmony_ci		ret = -1;
128662306a36Sopenharmony_ci		goto error_ret;
128762306a36Sopenharmony_ci	}
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	if (pbf_info->p1_low == 0) {
129062306a36Sopenharmony_ci		debug_printf("CLX: minimum base frequency not set\n");
129162306a36Sopenharmony_ci		ret = -1;
129262306a36Sopenharmony_ci		goto error_ret;
129362306a36Sopenharmony_ci	}
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ci	/* convert frequencies back to ratios */
129662306a36Sopenharmony_ci	pbf_info->p1_high = pbf_info->p1_high / 100000;
129762306a36Sopenharmony_ci	pbf_info->p1_low = pbf_info->p1_low / 100000;
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci	/* create high priority cpu mask */
130062306a36Sopenharmony_ci	pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
130162306a36Sopenharmony_ci	for (i = 0; i < topo_max_cpus; i++) {
130262306a36Sopenharmony_ci		if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
130362306a36Sopenharmony_ci			continue;
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_ci		if (!is_cpu_in_power_domain(i, id))
130662306a36Sopenharmony_ci			continue;
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci		cpu_bf = parse_int_file(1,
130962306a36Sopenharmony_ci			"/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency",
131062306a36Sopenharmony_ci					i);
131162306a36Sopenharmony_ci		cpu_bf = cpu_bf / 100000;
131262306a36Sopenharmony_ci		if (cpu_bf == pbf_info->p1_high)
131362306a36Sopenharmony_ci			CPU_SET_S(i, pbf_info->core_cpumask_size,
131462306a36Sopenharmony_ci				  pbf_info->core_cpumask);
131562306a36Sopenharmony_ci	}
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	/* extra ctdp & pbf struct parameters */
131862306a36Sopenharmony_ci	ctdp_level->processed = 1;
131962306a36Sopenharmony_ci	ctdp_level->pbf_support = 1; /* PBF is always supported and enabled */
132062306a36Sopenharmony_ci	ctdp_level->pbf_enabled = 1;
132162306a36Sopenharmony_ci	ctdp_level->fact_support = 0; /* FACT is never supported */
132262306a36Sopenharmony_ci	ctdp_level->fact_enabled = 0;
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci	return 0;
132562306a36Sopenharmony_ci
132662306a36Sopenharmony_cierror_ret:
132762306a36Sopenharmony_ci	free_cpu_set(ctdp_level->core_cpumask);
132862306a36Sopenharmony_ci	return ret;
132962306a36Sopenharmony_ci}
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_cistatic void dump_clx_n_config_for_cpu(struct isst_id *id, void *arg1, void *arg2,
133262306a36Sopenharmony_ci				   void *arg3, void *arg4)
133362306a36Sopenharmony_ci{
133462306a36Sopenharmony_ci	int ret;
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	if (tdp_level != 0xff && tdp_level != 0) {
133762306a36Sopenharmony_ci		isst_display_error_info_message(1, "Invalid level", 1, tdp_level);
133862306a36Sopenharmony_ci		exit(0);
133962306a36Sopenharmony_ci	}
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	ret = clx_n_config(id);
134262306a36Sopenharmony_ci	if (ret) {
134362306a36Sopenharmony_ci		debug_printf("clx_n_config failed");
134462306a36Sopenharmony_ci	} else {
134562306a36Sopenharmony_ci		struct isst_pkg_ctdp_level_info *ctdp_level;
134662306a36Sopenharmony_ci		struct isst_pbf_info *pbf_info;
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci		ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
134962306a36Sopenharmony_ci		pbf_info = &ctdp_level->pbf_info;
135062306a36Sopenharmony_ci		clx_n_pkg_dev.processed = 1;
135162306a36Sopenharmony_ci		isst_ctdp_display_information(id, outf, tdp_level, &clx_n_pkg_dev);
135262306a36Sopenharmony_ci		free_cpu_set(ctdp_level->core_cpumask);
135362306a36Sopenharmony_ci		free_cpu_set(pbf_info->core_cpumask);
135462306a36Sopenharmony_ci	}
135562306a36Sopenharmony_ci}
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_cistatic void dump_isst_config_for_cpu(struct isst_id *id, void *arg1, void *arg2,
135862306a36Sopenharmony_ci				     void *arg3, void *arg4)
135962306a36Sopenharmony_ci{
136062306a36Sopenharmony_ci	struct isst_pkg_ctdp pkg_dev;
136162306a36Sopenharmony_ci	int ret;
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	memset(&pkg_dev, 0, sizeof(pkg_dev));
136462306a36Sopenharmony_ci	ret = isst_get_process_ctdp(id, tdp_level, &pkg_dev);
136562306a36Sopenharmony_ci	if (ret) {
136662306a36Sopenharmony_ci		isst_display_error_info_message(1, "Failed to get perf-profile info on cpu", 1, id->cpu);
136762306a36Sopenharmony_ci		isst_ctdp_display_information_end(outf);
136862306a36Sopenharmony_ci		exit(1);
136962306a36Sopenharmony_ci	} else {
137062306a36Sopenharmony_ci		isst_ctdp_display_information(id, outf, tdp_level, &pkg_dev);
137162306a36Sopenharmony_ci		isst_get_process_ctdp_complete(id, &pkg_dev);
137262306a36Sopenharmony_ci	}
137362306a36Sopenharmony_ci}
137462306a36Sopenharmony_ci
137562306a36Sopenharmony_cistatic void dump_isst_config(int arg)
137662306a36Sopenharmony_ci{
137762306a36Sopenharmony_ci	void *fn;
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ci	if (cmd_help) {
138062306a36Sopenharmony_ci		fprintf(stderr,
138162306a36Sopenharmony_ci			"Print Intel(R) Speed Select Technology Performance profile configuration\n");
138262306a36Sopenharmony_ci		fprintf(stderr,
138362306a36Sopenharmony_ci			"including base frequency and turbo frequency configurations\n");
138462306a36Sopenharmony_ci		fprintf(stderr, "Optional: -l|--level : Specify tdp level\n");
138562306a36Sopenharmony_ci		fprintf(stderr,
138662306a36Sopenharmony_ci			"\tIf no arguments, dump information for all TDP levels\n");
138762306a36Sopenharmony_ci		exit(0);
138862306a36Sopenharmony_ci	}
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	if (!is_clx_n_platform())
139162306a36Sopenharmony_ci		fn = dump_isst_config_for_cpu;
139262306a36Sopenharmony_ci	else
139362306a36Sopenharmony_ci		fn = dump_clx_n_config_for_cpu;
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci	if (max_target_cpus)
139862306a36Sopenharmony_ci		for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
139962306a36Sopenharmony_ci	else
140062306a36Sopenharmony_ci		for_each_online_power_domain_in_set(fn, NULL, NULL, NULL, NULL);
140162306a36Sopenharmony_ci
140262306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
140362306a36Sopenharmony_ci}
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_cistatic void adjust_scaling_max_from_base_freq(int cpu);
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_cistatic void set_tdp_level_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
140862306a36Sopenharmony_ci				  void *arg4)
140962306a36Sopenharmony_ci{
141062306a36Sopenharmony_ci	struct isst_pkg_ctdp pkg_dev;
141162306a36Sopenharmony_ci	int ret;
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci	ret = isst_get_ctdp_levels(id, &pkg_dev);
141462306a36Sopenharmony_ci	if (ret) {
141562306a36Sopenharmony_ci		isst_display_error_info_message(1, "Get TDP level failed", 0, 0);
141662306a36Sopenharmony_ci		isst_ctdp_display_information_end(outf);
141762306a36Sopenharmony_ci		exit(1);
141862306a36Sopenharmony_ci	}
141962306a36Sopenharmony_ci
142062306a36Sopenharmony_ci	if (pkg_dev.current_level == tdp_level) {
142162306a36Sopenharmony_ci		debug_printf("TDP level already set. Skipped\n");
142262306a36Sopenharmony_ci		goto display_result;
142362306a36Sopenharmony_ci	}
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_ci	ret = isst_set_tdp_level(id, tdp_level);
142662306a36Sopenharmony_ci	if (ret) {
142762306a36Sopenharmony_ci		isst_display_error_info_message(1, "Set TDP level failed", 0, 0);
142862306a36Sopenharmony_ci		isst_ctdp_display_information_end(outf);
142962306a36Sopenharmony_ci		exit(1);
143062306a36Sopenharmony_ci	}
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_cidisplay_result:
143362306a36Sopenharmony_ci	isst_display_result(id, outf, "perf-profile", "set_tdp_level", ret);
143462306a36Sopenharmony_ci	if (force_online_offline && id->cpu >= 0) {
143562306a36Sopenharmony_ci		struct isst_pkg_ctdp_level_info ctdp_level;
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci		/* Wait for updated base frequencies */
143862306a36Sopenharmony_ci		usleep(2000);
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci		/* Adjusting uncore freq */
144162306a36Sopenharmony_ci		isst_adjust_uncore_freq(id, tdp_level, &ctdp_level);
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci		fprintf(stderr, "Option is set to online/offline\n");
144462306a36Sopenharmony_ci		ctdp_level.core_cpumask_size =
144562306a36Sopenharmony_ci			alloc_cpu_set(&ctdp_level.core_cpumask);
144662306a36Sopenharmony_ci		ret = isst_get_coremask_info(id, tdp_level, &ctdp_level);
144762306a36Sopenharmony_ci		if (ret) {
144862306a36Sopenharmony_ci			isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0);
144962306a36Sopenharmony_ci			goto free_mask;
145062306a36Sopenharmony_ci		}
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_ci		if (use_cgroupv2()) {
145362306a36Sopenharmony_ci			int ret;
145462306a36Sopenharmony_ci
145562306a36Sopenharmony_ci			fprintf(stderr, "Using cgroup v2 in lieu of online/offline\n");
145662306a36Sopenharmony_ci			ret = enable_cpuset_controller();
145762306a36Sopenharmony_ci			if (ret)
145862306a36Sopenharmony_ci				goto use_offline;
145962306a36Sopenharmony_ci
146062306a36Sopenharmony_ci			ret = isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask, tdp_level);
146162306a36Sopenharmony_ci			if (ret)
146262306a36Sopenharmony_ci				goto use_offline;
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci			goto free_mask;
146562306a36Sopenharmony_ci		}
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ciuse_offline:
146862306a36Sopenharmony_ci		if (ctdp_level.cpu_count) {
146962306a36Sopenharmony_ci			int i, max_cpus = get_topo_max_cpus();
147062306a36Sopenharmony_ci			for (i = 0; i < max_cpus; ++i) {
147162306a36Sopenharmony_ci				if (!is_cpu_in_power_domain(i, id))
147262306a36Sopenharmony_ci					continue;
147362306a36Sopenharmony_ci				if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
147462306a36Sopenharmony_ci					fprintf(stderr, "online cpu %d\n", i);
147562306a36Sopenharmony_ci					set_cpu_online_offline(i, 1);
147662306a36Sopenharmony_ci					adjust_scaling_max_from_base_freq(i);
147762306a36Sopenharmony_ci				} else {
147862306a36Sopenharmony_ci					fprintf(stderr, "offline cpu %d\n", i);
147962306a36Sopenharmony_ci					set_cpu_online_offline(i, 0);
148062306a36Sopenharmony_ci				}
148162306a36Sopenharmony_ci			}
148262306a36Sopenharmony_ci		}
148362306a36Sopenharmony_cifree_mask:
148462306a36Sopenharmony_ci		free_cpu_set(ctdp_level.core_cpumask);
148562306a36Sopenharmony_ci	}
148662306a36Sopenharmony_ci}
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_cistatic void set_tdp_level(int arg)
148962306a36Sopenharmony_ci{
149062306a36Sopenharmony_ci	if (cmd_help) {
149162306a36Sopenharmony_ci		fprintf(stderr, "Set Config TDP level\n");
149262306a36Sopenharmony_ci		fprintf(stderr,
149362306a36Sopenharmony_ci			"\t Arguments: -l|--level : Specify tdp level\n");
149462306a36Sopenharmony_ci		fprintf(stderr,
149562306a36Sopenharmony_ci			"\t Optional Arguments: -o | online : online/offline for the tdp level\n");
149662306a36Sopenharmony_ci		fprintf(stderr,
149762306a36Sopenharmony_ci			"\t  online/offline operation has limitations, refer to Linux hotplug documentation\n");
149862306a36Sopenharmony_ci		exit(0);
149962306a36Sopenharmony_ci	}
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_ci	if (tdp_level == 0xff) {
150262306a36Sopenharmony_ci		isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0);
150362306a36Sopenharmony_ci		exit(1);
150462306a36Sopenharmony_ci	}
150562306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
150662306a36Sopenharmony_ci	if (max_target_cpus)
150762306a36Sopenharmony_ci		for_each_online_target_cpu_in_set(set_tdp_level_for_cpu, NULL,
150862306a36Sopenharmony_ci						  NULL, NULL, NULL);
150962306a36Sopenharmony_ci	else
151062306a36Sopenharmony_ci		for_each_online_power_domain_in_set(set_tdp_level_for_cpu, NULL,
151162306a36Sopenharmony_ci					       NULL, NULL, NULL);
151262306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
151362306a36Sopenharmony_ci}
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_cistatic void clx_n_dump_pbf_config_for_cpu(struct isst_id *id, void *arg1, void *arg2,
151662306a36Sopenharmony_ci				       void *arg3, void *arg4)
151762306a36Sopenharmony_ci{
151862306a36Sopenharmony_ci	int ret;
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ci	ret = clx_n_config(id);
152162306a36Sopenharmony_ci	if (ret) {
152262306a36Sopenharmony_ci		isst_display_error_info_message(1, "clx_n_config failed", 0, 0);
152362306a36Sopenharmony_ci	} else {
152462306a36Sopenharmony_ci		struct isst_pkg_ctdp_level_info *ctdp_level;
152562306a36Sopenharmony_ci		struct isst_pbf_info *pbf_info;
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci		ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
152862306a36Sopenharmony_ci		pbf_info = &ctdp_level->pbf_info;
152962306a36Sopenharmony_ci		isst_pbf_display_information(id, outf, tdp_level, pbf_info);
153062306a36Sopenharmony_ci		free_cpu_set(ctdp_level->core_cpumask);
153162306a36Sopenharmony_ci		free_cpu_set(pbf_info->core_cpumask);
153262306a36Sopenharmony_ci	}
153362306a36Sopenharmony_ci}
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_cistatic void dump_pbf_config_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
153662306a36Sopenharmony_ci				    void *arg4)
153762306a36Sopenharmony_ci{
153862306a36Sopenharmony_ci	struct isst_pbf_info pbf_info;
153962306a36Sopenharmony_ci	int ret;
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci	ret = isst_get_pbf_info(id, tdp_level, &pbf_info);
154262306a36Sopenharmony_ci	if (ret) {
154362306a36Sopenharmony_ci		isst_display_error_info_message(1, "Failed to get base-freq info at this level", 1, tdp_level);
154462306a36Sopenharmony_ci		isst_ctdp_display_information_end(outf);
154562306a36Sopenharmony_ci		exit(1);
154662306a36Sopenharmony_ci	} else {
154762306a36Sopenharmony_ci		isst_pbf_display_information(id, outf, tdp_level, &pbf_info);
154862306a36Sopenharmony_ci		free_cpu_set(pbf_info.core_cpumask);
154962306a36Sopenharmony_ci	}
155062306a36Sopenharmony_ci}
155162306a36Sopenharmony_ci
155262306a36Sopenharmony_cistatic void dump_pbf_config(int arg)
155362306a36Sopenharmony_ci{
155462306a36Sopenharmony_ci	void *fn;
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci	if (cmd_help) {
155762306a36Sopenharmony_ci		fprintf(stderr,
155862306a36Sopenharmony_ci			"Print Intel(R) Speed Select Technology base frequency configuration for a TDP level\n");
155962306a36Sopenharmony_ci		fprintf(stderr,
156062306a36Sopenharmony_ci			"\tArguments: -l|--level : Specify tdp level\n");
156162306a36Sopenharmony_ci		exit(0);
156262306a36Sopenharmony_ci	}
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_ci	if (tdp_level == 0xff) {
156562306a36Sopenharmony_ci		isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0);
156662306a36Sopenharmony_ci		exit(1);
156762306a36Sopenharmony_ci	}
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ci	if (!is_clx_n_platform())
157062306a36Sopenharmony_ci		fn = dump_pbf_config_for_cpu;
157162306a36Sopenharmony_ci	else
157262306a36Sopenharmony_ci		fn = clx_n_dump_pbf_config_for_cpu;
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	if (max_target_cpus)
157762306a36Sopenharmony_ci		for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
157862306a36Sopenharmony_ci	else
157962306a36Sopenharmony_ci		for_each_online_power_domain_in_set(fn, NULL, NULL, NULL, NULL);
158062306a36Sopenharmony_ci
158162306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
158262306a36Sopenharmony_ci}
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_cistatic int set_clos_param(struct isst_id *id, int clos, int epp, int wt, int min, int max)
158562306a36Sopenharmony_ci{
158662306a36Sopenharmony_ci	struct isst_clos_config clos_config;
158762306a36Sopenharmony_ci	int ret;
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_ci	ret = isst_pm_get_clos(id, clos, &clos_config);
159062306a36Sopenharmony_ci	if (ret) {
159162306a36Sopenharmony_ci		isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
159262306a36Sopenharmony_ci		return ret;
159362306a36Sopenharmony_ci	}
159462306a36Sopenharmony_ci	clos_config.clos_min = min;
159562306a36Sopenharmony_ci	clos_config.clos_max = max;
159662306a36Sopenharmony_ci	clos_config.epp = epp;
159762306a36Sopenharmony_ci	clos_config.clos_prop_prio = wt;
159862306a36Sopenharmony_ci	ret = isst_set_clos(id, clos, &clos_config);
159962306a36Sopenharmony_ci	if (ret) {
160062306a36Sopenharmony_ci		isst_display_error_info_message(1, "isst_set_clos failed", 0, 0);
160162306a36Sopenharmony_ci		return ret;
160262306a36Sopenharmony_ci	}
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci	return 0;
160562306a36Sopenharmony_ci}
160662306a36Sopenharmony_ci
160762306a36Sopenharmony_cistatic int set_cpufreq_scaling_min_max(int cpu, int max, int freq)
160862306a36Sopenharmony_ci{
160962306a36Sopenharmony_ci	char buffer[128], freq_str[16];
161062306a36Sopenharmony_ci	int fd, ret, len;
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_ci	if (max)
161362306a36Sopenharmony_ci		snprintf(buffer, sizeof(buffer),
161462306a36Sopenharmony_ci			 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
161562306a36Sopenharmony_ci	else
161662306a36Sopenharmony_ci		snprintf(buffer, sizeof(buffer),
161762306a36Sopenharmony_ci			 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
161862306a36Sopenharmony_ci
161962306a36Sopenharmony_ci	fd = open(buffer, O_WRONLY);
162062306a36Sopenharmony_ci	if (fd < 0)
162162306a36Sopenharmony_ci		return fd;
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci	snprintf(freq_str, sizeof(freq_str), "%d", freq);
162462306a36Sopenharmony_ci	len = strlen(freq_str);
162562306a36Sopenharmony_ci	ret = write(fd, freq_str, len);
162662306a36Sopenharmony_ci	if (ret == -1) {
162762306a36Sopenharmony_ci		close(fd);
162862306a36Sopenharmony_ci		return ret;
162962306a36Sopenharmony_ci	}
163062306a36Sopenharmony_ci	close(fd);
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	return 0;
163362306a36Sopenharmony_ci}
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_cistatic int no_turbo(void)
163662306a36Sopenharmony_ci{
163762306a36Sopenharmony_ci	return parse_int_file(0, "/sys/devices/system/cpu/intel_pstate/no_turbo");
163862306a36Sopenharmony_ci}
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_cistatic void adjust_scaling_max_from_base_freq(int cpu)
164162306a36Sopenharmony_ci{
164262306a36Sopenharmony_ci	int base_freq, scaling_max_freq;
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci	scaling_max_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
164562306a36Sopenharmony_ci	base_freq = get_cpufreq_base_freq(cpu);
164662306a36Sopenharmony_ci	if (scaling_max_freq < base_freq || no_turbo())
164762306a36Sopenharmony_ci		set_cpufreq_scaling_min_max(cpu, 1, base_freq);
164862306a36Sopenharmony_ci}
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_cistatic void adjust_scaling_min_from_base_freq(int cpu)
165162306a36Sopenharmony_ci{
165262306a36Sopenharmony_ci	int base_freq, scaling_min_freq;
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci	scaling_min_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
165562306a36Sopenharmony_ci	base_freq = get_cpufreq_base_freq(cpu);
165662306a36Sopenharmony_ci	if (scaling_min_freq < base_freq)
165762306a36Sopenharmony_ci		set_cpufreq_scaling_min_max(cpu, 0, base_freq);
165862306a36Sopenharmony_ci}
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_cistatic int set_clx_pbf_cpufreq_scaling_min_max(struct isst_id *id)
166162306a36Sopenharmony_ci{
166262306a36Sopenharmony_ci	struct isst_pkg_ctdp_level_info *ctdp_level;
166362306a36Sopenharmony_ci	struct isst_pbf_info *pbf_info;
166462306a36Sopenharmony_ci	int i, freq, freq_high, freq_low;
166562306a36Sopenharmony_ci	int ret;
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci	ret = clx_n_config(id);
166862306a36Sopenharmony_ci	if (ret) {
166962306a36Sopenharmony_ci		debug_printf("cpufreq_scaling_min_max failed for CLX");
167062306a36Sopenharmony_ci		return ret;
167162306a36Sopenharmony_ci	}
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci	ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
167462306a36Sopenharmony_ci	pbf_info = &ctdp_level->pbf_info;
167562306a36Sopenharmony_ci	freq_high = pbf_info->p1_high * 100000;
167662306a36Sopenharmony_ci	freq_low = pbf_info->p1_low * 100000;
167762306a36Sopenharmony_ci
167862306a36Sopenharmony_ci	for (i = 0; i < get_topo_max_cpus(); ++i) {
167962306a36Sopenharmony_ci		if (!is_cpu_in_power_domain(i, id))
168062306a36Sopenharmony_ci			continue;
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci		if (CPU_ISSET_S(i, pbf_info->core_cpumask_size,
168362306a36Sopenharmony_ci				  pbf_info->core_cpumask))
168462306a36Sopenharmony_ci			freq = freq_high;
168562306a36Sopenharmony_ci		else
168662306a36Sopenharmony_ci			freq = freq_low;
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci		set_cpufreq_scaling_min_max(i, 1, freq);
168962306a36Sopenharmony_ci		set_cpufreq_scaling_min_max(i, 0, freq);
169062306a36Sopenharmony_ci	}
169162306a36Sopenharmony_ci
169262306a36Sopenharmony_ci	return 0;
169362306a36Sopenharmony_ci}
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_cistatic int set_cpufreq_scaling_min_max_from_cpuinfo(int cpu, int cpuinfo_max, int scaling_max)
169662306a36Sopenharmony_ci{
169762306a36Sopenharmony_ci	char buffer[128], min_freq[16];
169862306a36Sopenharmony_ci	int fd, ret, len;
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_ci	if (!CPU_ISSET_S(cpu, present_cpumask_size, present_cpumask))
170162306a36Sopenharmony_ci		return -1;
170262306a36Sopenharmony_ci
170362306a36Sopenharmony_ci	if (cpuinfo_max)
170462306a36Sopenharmony_ci		snprintf(buffer, sizeof(buffer),
170562306a36Sopenharmony_ci			 "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpu);
170662306a36Sopenharmony_ci	else
170762306a36Sopenharmony_ci		snprintf(buffer, sizeof(buffer),
170862306a36Sopenharmony_ci			 "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_min_freq", cpu);
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_ci	fd = open(buffer, O_RDONLY);
171162306a36Sopenharmony_ci	if (fd < 0)
171262306a36Sopenharmony_ci		return fd;
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_ci	len = read(fd, min_freq, sizeof(min_freq));
171562306a36Sopenharmony_ci	close(fd);
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_ci	if (len < 0)
171862306a36Sopenharmony_ci		return len;
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	if (scaling_max)
172162306a36Sopenharmony_ci		snprintf(buffer, sizeof(buffer),
172262306a36Sopenharmony_ci			 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
172362306a36Sopenharmony_ci	else
172462306a36Sopenharmony_ci		snprintf(buffer, sizeof(buffer),
172562306a36Sopenharmony_ci			 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	fd = open(buffer, O_WRONLY);
172862306a36Sopenharmony_ci	if (fd < 0)
172962306a36Sopenharmony_ci		return fd;
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci	min_freq[15] = '\0';
173262306a36Sopenharmony_ci	len = strlen(min_freq);
173362306a36Sopenharmony_ci	ret = write(fd, min_freq, len);
173462306a36Sopenharmony_ci	if (ret == -1) {
173562306a36Sopenharmony_ci		close(fd);
173662306a36Sopenharmony_ci		return ret;
173762306a36Sopenharmony_ci	}
173862306a36Sopenharmony_ci	close(fd);
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ci	return 0;
174162306a36Sopenharmony_ci}
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_cistatic void set_scaling_min_to_cpuinfo_max(struct isst_id *id)
174462306a36Sopenharmony_ci{
174562306a36Sopenharmony_ci	int i;
174662306a36Sopenharmony_ci
174762306a36Sopenharmony_ci	if (id->cpu < 0)
174862306a36Sopenharmony_ci		return;
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ci	for (i = 0; i < get_topo_max_cpus(); ++i) {
175162306a36Sopenharmony_ci		if (!is_cpu_in_power_domain(i, id))
175262306a36Sopenharmony_ci			continue;
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ci		if (is_cpu_online(i) != 1)
175562306a36Sopenharmony_ci			continue;
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci		adjust_scaling_max_from_base_freq(i);
175862306a36Sopenharmony_ci		set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 0);
175962306a36Sopenharmony_ci		adjust_scaling_min_from_base_freq(i);
176062306a36Sopenharmony_ci	}
176162306a36Sopenharmony_ci}
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_cistatic void set_scaling_min_to_cpuinfo_min(struct isst_id *id)
176462306a36Sopenharmony_ci{
176562306a36Sopenharmony_ci	int i;
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_ci	if (id->cpu < 0)
176862306a36Sopenharmony_ci		return;
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ci	for (i = 0; i < get_topo_max_cpus(); ++i) {
177162306a36Sopenharmony_ci		if (!is_cpu_in_power_domain(i, id))
177262306a36Sopenharmony_ci			continue;
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_ci		if (is_cpu_online(i) != 1)
177562306a36Sopenharmony_ci			continue;
177662306a36Sopenharmony_ci
177762306a36Sopenharmony_ci		adjust_scaling_max_from_base_freq(i);
177862306a36Sopenharmony_ci		set_cpufreq_scaling_min_max_from_cpuinfo(i, 0, 0);
177962306a36Sopenharmony_ci	}
178062306a36Sopenharmony_ci}
178162306a36Sopenharmony_ci
178262306a36Sopenharmony_cistatic void set_scaling_max_to_cpuinfo_max(struct isst_id *id)
178362306a36Sopenharmony_ci{
178462306a36Sopenharmony_ci	int i;
178562306a36Sopenharmony_ci
178662306a36Sopenharmony_ci	for (i = 0; i < get_topo_max_cpus(); ++i) {
178762306a36Sopenharmony_ci		if (!is_cpu_in_power_domain(i, id))
178862306a36Sopenharmony_ci			continue;
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci		set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 1);
179162306a36Sopenharmony_ci	}
179262306a36Sopenharmony_ci}
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_cistatic int set_core_priority_and_min(struct isst_id *id, int mask_size,
179562306a36Sopenharmony_ci				     cpu_set_t *cpu_mask, int min_high,
179662306a36Sopenharmony_ci				     int min_low)
179762306a36Sopenharmony_ci{
179862306a36Sopenharmony_ci	int ret, i;
179962306a36Sopenharmony_ci
180062306a36Sopenharmony_ci	if (!CPU_COUNT_S(mask_size, cpu_mask))
180162306a36Sopenharmony_ci		return -1;
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_ci	ret = set_clos_param(id, 0, 0, 0, min_high, 0xff);
180462306a36Sopenharmony_ci	if (ret)
180562306a36Sopenharmony_ci		return ret;
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci	ret = set_clos_param(id, 1, 15, 15, min_low, 0xff);
180862306a36Sopenharmony_ci	if (ret)
180962306a36Sopenharmony_ci		return ret;
181062306a36Sopenharmony_ci
181162306a36Sopenharmony_ci	ret = set_clos_param(id, 2, 15, 15, min_low, 0xff);
181262306a36Sopenharmony_ci	if (ret)
181362306a36Sopenharmony_ci		return ret;
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci	ret = set_clos_param(id, 3, 15, 15, min_low, 0xff);
181662306a36Sopenharmony_ci	if (ret)
181762306a36Sopenharmony_ci		return ret;
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci	for (i = 0; i < get_topo_max_cpus(); ++i) {
182062306a36Sopenharmony_ci		int clos;
182162306a36Sopenharmony_ci		struct isst_id tid;
182262306a36Sopenharmony_ci
182362306a36Sopenharmony_ci		if (!is_cpu_in_power_domain(i, id))
182462306a36Sopenharmony_ci			continue;
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_ci		if (CPU_ISSET_S(i, mask_size, cpu_mask))
182762306a36Sopenharmony_ci			clos = 0;
182862306a36Sopenharmony_ci		else
182962306a36Sopenharmony_ci			clos = 3;
183062306a36Sopenharmony_ci
183162306a36Sopenharmony_ci		debug_printf("Associate cpu: %d clos: %d\n", i, clos);
183262306a36Sopenharmony_ci		set_isst_id(&tid, i);
183362306a36Sopenharmony_ci		ret = isst_clos_associate(&tid, clos);
183462306a36Sopenharmony_ci		if (ret) {
183562306a36Sopenharmony_ci			isst_display_error_info_message(1, "isst_clos_associate failed", 0, 0);
183662306a36Sopenharmony_ci			return ret;
183762306a36Sopenharmony_ci		}
183862306a36Sopenharmony_ci	}
183962306a36Sopenharmony_ci
184062306a36Sopenharmony_ci	return 0;
184162306a36Sopenharmony_ci}
184262306a36Sopenharmony_ci
184362306a36Sopenharmony_cistatic int set_pbf_core_power(struct isst_id *id)
184462306a36Sopenharmony_ci{
184562306a36Sopenharmony_ci	struct isst_pbf_info pbf_info;
184662306a36Sopenharmony_ci	struct isst_pkg_ctdp pkg_dev;
184762306a36Sopenharmony_ci	int ret;
184862306a36Sopenharmony_ci
184962306a36Sopenharmony_ci	if (id->cpu < 0)
185062306a36Sopenharmony_ci		return 0;
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_ci	ret = isst_get_ctdp_levels(id, &pkg_dev);
185362306a36Sopenharmony_ci	if (ret) {
185462306a36Sopenharmony_ci		debug_printf("isst_get_ctdp_levels failed");
185562306a36Sopenharmony_ci		return ret;
185662306a36Sopenharmony_ci	}
185762306a36Sopenharmony_ci	debug_printf("Current_level: %d\n", pkg_dev.current_level);
185862306a36Sopenharmony_ci
185962306a36Sopenharmony_ci	ret = isst_get_pbf_info(id, pkg_dev.current_level, &pbf_info);
186062306a36Sopenharmony_ci	if (ret) {
186162306a36Sopenharmony_ci		debug_printf("isst_get_pbf_info failed");
186262306a36Sopenharmony_ci		return ret;
186362306a36Sopenharmony_ci	}
186462306a36Sopenharmony_ci	debug_printf("p1_high: %d p1_low: %d\n", pbf_info.p1_high,
186562306a36Sopenharmony_ci		     pbf_info.p1_low);
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci	ret = set_core_priority_and_min(id, pbf_info.core_cpumask_size,
186862306a36Sopenharmony_ci					pbf_info.core_cpumask,
186962306a36Sopenharmony_ci					pbf_info.p1_high, pbf_info.p1_low);
187062306a36Sopenharmony_ci	if (ret) {
187162306a36Sopenharmony_ci		debug_printf("set_core_priority_and_min failed");
187262306a36Sopenharmony_ci		return ret;
187362306a36Sopenharmony_ci	}
187462306a36Sopenharmony_ci
187562306a36Sopenharmony_ci	ret = isst_pm_qos_config(id, 1, 1);
187662306a36Sopenharmony_ci	if (ret) {
187762306a36Sopenharmony_ci		debug_printf("isst_pm_qos_config failed");
187862306a36Sopenharmony_ci		return ret;
187962306a36Sopenharmony_ci	}
188062306a36Sopenharmony_ci
188162306a36Sopenharmony_ci	return 0;
188262306a36Sopenharmony_ci}
188362306a36Sopenharmony_ci
188462306a36Sopenharmony_cistatic void set_pbf_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
188562306a36Sopenharmony_ci			    void *arg4)
188662306a36Sopenharmony_ci{
188762306a36Sopenharmony_ci	struct isst_pkg_ctdp_level_info ctdp_level;
188862306a36Sopenharmony_ci	struct isst_pkg_ctdp pkg_dev;
188962306a36Sopenharmony_ci	int ret;
189062306a36Sopenharmony_ci	int status = *(int *)arg4;
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	if (is_clx_n_platform()) {
189362306a36Sopenharmony_ci		ret = 0;
189462306a36Sopenharmony_ci		if (status) {
189562306a36Sopenharmony_ci			set_clx_pbf_cpufreq_scaling_min_max(id);
189662306a36Sopenharmony_ci
189762306a36Sopenharmony_ci		} else {
189862306a36Sopenharmony_ci			set_scaling_max_to_cpuinfo_max(id);
189962306a36Sopenharmony_ci			set_scaling_min_to_cpuinfo_min(id);
190062306a36Sopenharmony_ci		}
190162306a36Sopenharmony_ci		goto disp_result;
190262306a36Sopenharmony_ci	}
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci	ret = isst_get_ctdp_levels(id, &pkg_dev);
190562306a36Sopenharmony_ci	if (ret) {
190662306a36Sopenharmony_ci		isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
190762306a36Sopenharmony_ci		goto disp_result;
190862306a36Sopenharmony_ci	}
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	ret = isst_get_ctdp_control(id, pkg_dev.current_level, &ctdp_level);
191162306a36Sopenharmony_ci	if (ret) {
191262306a36Sopenharmony_ci		isst_display_error_info_message(1, "Failed to get current level", 0, 0);
191362306a36Sopenharmony_ci		goto disp_result;
191462306a36Sopenharmony_ci	}
191562306a36Sopenharmony_ci
191662306a36Sopenharmony_ci	if (!ctdp_level.pbf_support) {
191762306a36Sopenharmony_ci		isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, pkg_dev.current_level);
191862306a36Sopenharmony_ci		ret = -1;
191962306a36Sopenharmony_ci		goto disp_result;
192062306a36Sopenharmony_ci	}
192162306a36Sopenharmony_ci
192262306a36Sopenharmony_ci	if (auto_mode && status) {
192362306a36Sopenharmony_ci		ret = set_pbf_core_power(id);
192462306a36Sopenharmony_ci		if (ret)
192562306a36Sopenharmony_ci			goto disp_result;
192662306a36Sopenharmony_ci	}
192762306a36Sopenharmony_ci
192862306a36Sopenharmony_ci	ret = isst_set_pbf_fact_status(id, 1, status);
192962306a36Sopenharmony_ci	if (ret) {
193062306a36Sopenharmony_ci		debug_printf("isst_set_pbf_fact_status failed");
193162306a36Sopenharmony_ci		if (auto_mode)
193262306a36Sopenharmony_ci			isst_pm_qos_config(id, 0, 0);
193362306a36Sopenharmony_ci	} else {
193462306a36Sopenharmony_ci		if (auto_mode) {
193562306a36Sopenharmony_ci			if (status)
193662306a36Sopenharmony_ci				set_scaling_min_to_cpuinfo_max(id);
193762306a36Sopenharmony_ci			else
193862306a36Sopenharmony_ci				set_scaling_min_to_cpuinfo_min(id);
193962306a36Sopenharmony_ci		}
194062306a36Sopenharmony_ci	}
194162306a36Sopenharmony_ci
194262306a36Sopenharmony_ci	if (auto_mode && !status)
194362306a36Sopenharmony_ci		isst_pm_qos_config(id, 0, 1);
194462306a36Sopenharmony_ci
194562306a36Sopenharmony_cidisp_result:
194662306a36Sopenharmony_ci	if (status)
194762306a36Sopenharmony_ci		isst_display_result(id, outf, "base-freq", "enable",
194862306a36Sopenharmony_ci				    ret);
194962306a36Sopenharmony_ci	else
195062306a36Sopenharmony_ci		isst_display_result(id, outf, "base-freq", "disable",
195162306a36Sopenharmony_ci				    ret);
195262306a36Sopenharmony_ci}
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_cistatic void set_pbf_enable(int arg)
195562306a36Sopenharmony_ci{
195662306a36Sopenharmony_ci	int enable = arg;
195762306a36Sopenharmony_ci
195862306a36Sopenharmony_ci	if (cmd_help) {
195962306a36Sopenharmony_ci		if (enable) {
196062306a36Sopenharmony_ci			fprintf(stderr,
196162306a36Sopenharmony_ci				"Enable Intel Speed Select Technology base frequency feature\n");
196262306a36Sopenharmony_ci			if (is_clx_n_platform()) {
196362306a36Sopenharmony_ci				fprintf(stderr,
196462306a36Sopenharmony_ci					"\tOn this platform this command doesn't enable feature in the hardware.\n");
196562306a36Sopenharmony_ci				fprintf(stderr,
196662306a36Sopenharmony_ci					"\tIt updates the cpufreq scaling_min_freq to match cpufreq base_frequency.\n");
196762306a36Sopenharmony_ci				exit(0);
196862306a36Sopenharmony_ci
196962306a36Sopenharmony_ci			}
197062306a36Sopenharmony_ci			fprintf(stderr,
197162306a36Sopenharmony_ci				"\tOptional Arguments: -a|--auto : Use priority of cores to set core-power associations\n");
197262306a36Sopenharmony_ci		} else {
197362306a36Sopenharmony_ci
197462306a36Sopenharmony_ci			if (is_clx_n_platform()) {
197562306a36Sopenharmony_ci				fprintf(stderr,
197662306a36Sopenharmony_ci					"\tOn this platform this command doesn't disable feature in the hardware.\n");
197762306a36Sopenharmony_ci				fprintf(stderr,
197862306a36Sopenharmony_ci					"\tIt updates the cpufreq scaling_min_freq to match cpuinfo_min_freq\n");
197962306a36Sopenharmony_ci				exit(0);
198062306a36Sopenharmony_ci			}
198162306a36Sopenharmony_ci			fprintf(stderr,
198262306a36Sopenharmony_ci				"Disable Intel Speed Select Technology base frequency feature\n");
198362306a36Sopenharmony_ci			fprintf(stderr,
198462306a36Sopenharmony_ci				"\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
198562306a36Sopenharmony_ci		}
198662306a36Sopenharmony_ci		exit(0);
198762306a36Sopenharmony_ci	}
198862306a36Sopenharmony_ci
198962306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
199062306a36Sopenharmony_ci	if (max_target_cpus)
199162306a36Sopenharmony_ci		for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
199262306a36Sopenharmony_ci						  NULL, &enable);
199362306a36Sopenharmony_ci	else
199462306a36Sopenharmony_ci		for_each_online_power_domain_in_set(set_pbf_for_cpu, NULL, NULL,
199562306a36Sopenharmony_ci					       NULL, &enable);
199662306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
199762306a36Sopenharmony_ci}
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_cistatic void dump_fact_config_for_cpu(struct isst_id *id, void *arg1, void *arg2,
200062306a36Sopenharmony_ci				     void *arg3, void *arg4)
200162306a36Sopenharmony_ci{
200262306a36Sopenharmony_ci	struct isst_fact_info fact_info;
200362306a36Sopenharmony_ci	int ret;
200462306a36Sopenharmony_ci
200562306a36Sopenharmony_ci	ret = isst_get_fact_info(id, tdp_level, fact_bucket, &fact_info);
200662306a36Sopenharmony_ci	if (ret) {
200762306a36Sopenharmony_ci		isst_display_error_info_message(1, "Failed to get turbo-freq info at this level", 1, tdp_level);
200862306a36Sopenharmony_ci		isst_ctdp_display_information_end(outf);
200962306a36Sopenharmony_ci		exit(1);
201062306a36Sopenharmony_ci	} else {
201162306a36Sopenharmony_ci		isst_fact_display_information(id, outf, tdp_level, fact_bucket,
201262306a36Sopenharmony_ci					      fact_avx, &fact_info);
201362306a36Sopenharmony_ci	}
201462306a36Sopenharmony_ci}
201562306a36Sopenharmony_ci
201662306a36Sopenharmony_cistatic void dump_fact_config(int arg)
201762306a36Sopenharmony_ci{
201862306a36Sopenharmony_ci	if (cmd_help) {
201962306a36Sopenharmony_ci		fprintf(stderr,
202062306a36Sopenharmony_ci			"Print complete Intel Speed Select Technology turbo frequency configuration for a TDP level. Other arguments are optional.\n");
202162306a36Sopenharmony_ci		fprintf(stderr,
202262306a36Sopenharmony_ci			"\tArguments: -l|--level : Specify tdp level\n");
202362306a36Sopenharmony_ci		fprintf(stderr,
202462306a36Sopenharmony_ci			"\tArguments: -b|--bucket : Bucket index to dump\n");
202562306a36Sopenharmony_ci		fprintf(stderr,
202662306a36Sopenharmony_ci			"\tArguments: -r|--trl-type : Specify trl type: sse|avx2|avx512\n");
202762306a36Sopenharmony_ci		exit(0);
202862306a36Sopenharmony_ci	}
202962306a36Sopenharmony_ci
203062306a36Sopenharmony_ci	if (tdp_level == 0xff) {
203162306a36Sopenharmony_ci		isst_display_error_info_message(1, "Invalid command: specify tdp_level\n", 0, 0);
203262306a36Sopenharmony_ci		exit(1);
203362306a36Sopenharmony_ci	}
203462306a36Sopenharmony_ci
203562306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
203662306a36Sopenharmony_ci	if (max_target_cpus)
203762306a36Sopenharmony_ci		for_each_online_target_cpu_in_set(dump_fact_config_for_cpu,
203862306a36Sopenharmony_ci						  NULL, NULL, NULL, NULL);
203962306a36Sopenharmony_ci	else
204062306a36Sopenharmony_ci		for_each_online_power_domain_in_set(dump_fact_config_for_cpu, NULL,
204162306a36Sopenharmony_ci					       NULL, NULL, NULL);
204262306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
204362306a36Sopenharmony_ci}
204462306a36Sopenharmony_ci
204562306a36Sopenharmony_cistatic void set_fact_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
204662306a36Sopenharmony_ci			     void *arg4)
204762306a36Sopenharmony_ci{
204862306a36Sopenharmony_ci	struct isst_pkg_ctdp_level_info ctdp_level;
204962306a36Sopenharmony_ci	struct isst_pkg_ctdp pkg_dev;
205062306a36Sopenharmony_ci	int ret;
205162306a36Sopenharmony_ci	int status = *(int *)arg4;
205262306a36Sopenharmony_ci
205362306a36Sopenharmony_ci	if (status && no_turbo()) {
205462306a36Sopenharmony_ci		isst_display_error_info_message(1, "Turbo mode is disabled", 0, 0);
205562306a36Sopenharmony_ci		ret = -1;
205662306a36Sopenharmony_ci		goto disp_results;
205762306a36Sopenharmony_ci	}
205862306a36Sopenharmony_ci
205962306a36Sopenharmony_ci	ret = isst_get_ctdp_levels(id, &pkg_dev);
206062306a36Sopenharmony_ci	if (ret) {
206162306a36Sopenharmony_ci		isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
206262306a36Sopenharmony_ci		goto disp_results;
206362306a36Sopenharmony_ci	}
206462306a36Sopenharmony_ci
206562306a36Sopenharmony_ci	ret = isst_get_ctdp_control(id, pkg_dev.current_level, &ctdp_level);
206662306a36Sopenharmony_ci	if (ret) {
206762306a36Sopenharmony_ci		isst_display_error_info_message(1, "Failed to get current level", 0, 0);
206862306a36Sopenharmony_ci		goto disp_results;
206962306a36Sopenharmony_ci	}
207062306a36Sopenharmony_ci
207162306a36Sopenharmony_ci	if (!ctdp_level.fact_support) {
207262306a36Sopenharmony_ci		isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, pkg_dev.current_level);
207362306a36Sopenharmony_ci		ret = -1;
207462306a36Sopenharmony_ci		goto disp_results;
207562306a36Sopenharmony_ci	}
207662306a36Sopenharmony_ci
207762306a36Sopenharmony_ci	if (status) {
207862306a36Sopenharmony_ci		ret = isst_pm_qos_config(id, 1, 1);
207962306a36Sopenharmony_ci		if (ret)
208062306a36Sopenharmony_ci			goto disp_results;
208162306a36Sopenharmony_ci	}
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_ci	ret = isst_set_pbf_fact_status(id, 0, status);
208462306a36Sopenharmony_ci	if (ret) {
208562306a36Sopenharmony_ci		debug_printf("isst_set_pbf_fact_status failed");
208662306a36Sopenharmony_ci		if (auto_mode)
208762306a36Sopenharmony_ci			isst_pm_qos_config(id, 0, 0);
208862306a36Sopenharmony_ci
208962306a36Sopenharmony_ci		goto disp_results;
209062306a36Sopenharmony_ci	}
209162306a36Sopenharmony_ci
209262306a36Sopenharmony_ci	/* Set TRL */
209362306a36Sopenharmony_ci	if (status) {
209462306a36Sopenharmony_ci		struct isst_pkg_ctdp pkg_dev;
209562306a36Sopenharmony_ci
209662306a36Sopenharmony_ci		ret = isst_get_ctdp_levels(id, &pkg_dev);
209762306a36Sopenharmony_ci		if (!ret && id->cpu >= 0)
209862306a36Sopenharmony_ci			ret = isst_set_trl(id, fact_trl);
209962306a36Sopenharmony_ci		if (ret && auto_mode)
210062306a36Sopenharmony_ci			isst_pm_qos_config(id, 0, 0);
210162306a36Sopenharmony_ci	} else {
210262306a36Sopenharmony_ci		if (auto_mode)
210362306a36Sopenharmony_ci			isst_pm_qos_config(id, 0, 0);
210462306a36Sopenharmony_ci	}
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_cidisp_results:
210762306a36Sopenharmony_ci	if (status) {
210862306a36Sopenharmony_ci		isst_display_result(id, outf, "turbo-freq", "enable", ret);
210962306a36Sopenharmony_ci		if (ret)
211062306a36Sopenharmony_ci			fact_enable_fail = ret;
211162306a36Sopenharmony_ci	} else {
211262306a36Sopenharmony_ci		/* Since we modified TRL during Fact enable, restore it */
211362306a36Sopenharmony_ci		isst_set_trl_from_current_tdp(id, fact_trl);
211462306a36Sopenharmony_ci		isst_display_result(id, outf, "turbo-freq", "disable", ret);
211562306a36Sopenharmony_ci	}
211662306a36Sopenharmony_ci}
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_cistatic void set_fact_enable(int arg)
211962306a36Sopenharmony_ci{
212062306a36Sopenharmony_ci	int i, ret, enable = arg;
212162306a36Sopenharmony_ci	struct isst_id id;
212262306a36Sopenharmony_ci
212362306a36Sopenharmony_ci	if (cmd_help) {
212462306a36Sopenharmony_ci		if (enable) {
212562306a36Sopenharmony_ci			fprintf(stderr,
212662306a36Sopenharmony_ci				"Enable Intel Speed Select Technology Turbo frequency feature\n");
212762306a36Sopenharmony_ci			fprintf(stderr,
212862306a36Sopenharmony_ci				"Optional: -t|--trl : Specify turbo ratio limit\n");
212962306a36Sopenharmony_ci			fprintf(stderr,
213062306a36Sopenharmony_ci				"\tOptional Arguments: -a|--auto : Designate specified target CPUs with");
213162306a36Sopenharmony_ci			fprintf(stderr,
213262306a36Sopenharmony_ci				"-C|--cpu option as as high priority using core-power feature\n");
213362306a36Sopenharmony_ci		} else {
213462306a36Sopenharmony_ci			fprintf(stderr,
213562306a36Sopenharmony_ci				"Disable Intel Speed Select Technology turbo frequency feature\n");
213662306a36Sopenharmony_ci			fprintf(stderr,
213762306a36Sopenharmony_ci				"Optional: -t|--trl : Specify turbo ratio limit\n");
213862306a36Sopenharmony_ci			fprintf(stderr,
213962306a36Sopenharmony_ci				"\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
214062306a36Sopenharmony_ci		}
214162306a36Sopenharmony_ci		exit(0);
214262306a36Sopenharmony_ci	}
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
214562306a36Sopenharmony_ci	if (max_target_cpus)
214662306a36Sopenharmony_ci		for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
214762306a36Sopenharmony_ci						  NULL, &enable);
214862306a36Sopenharmony_ci	else
214962306a36Sopenharmony_ci		for_each_online_power_domain_in_set(set_fact_for_cpu, NULL, NULL,
215062306a36Sopenharmony_ci					       NULL, &enable);
215162306a36Sopenharmony_ci
215262306a36Sopenharmony_ci	if (!fact_enable_fail && enable && auto_mode) {
215362306a36Sopenharmony_ci		/*
215462306a36Sopenharmony_ci		 * When we adjust CLOS param, we have to set for siblings also.
215562306a36Sopenharmony_ci		 * So for the each user specified CPU, also add the sibling
215662306a36Sopenharmony_ci		 * in the present_cpu_mask.
215762306a36Sopenharmony_ci		 */
215862306a36Sopenharmony_ci		for (i = 0; i < get_topo_max_cpus(); ++i) {
215962306a36Sopenharmony_ci			char buffer[128], sibling_list[128], *cpu_str;
216062306a36Sopenharmony_ci			int fd, len;
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_ci			if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
216362306a36Sopenharmony_ci				continue;
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ci			snprintf(buffer, sizeof(buffer),
216662306a36Sopenharmony_ci				 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", i);
216762306a36Sopenharmony_ci
216862306a36Sopenharmony_ci			fd = open(buffer, O_RDONLY);
216962306a36Sopenharmony_ci			if (fd < 0)
217062306a36Sopenharmony_ci				continue;
217162306a36Sopenharmony_ci
217262306a36Sopenharmony_ci			len = read(fd, sibling_list, sizeof(sibling_list));
217362306a36Sopenharmony_ci			close(fd);
217462306a36Sopenharmony_ci
217562306a36Sopenharmony_ci			if (len < 0)
217662306a36Sopenharmony_ci				continue;
217762306a36Sopenharmony_ci
217862306a36Sopenharmony_ci			sibling_list[127] = '\0';
217962306a36Sopenharmony_ci			cpu_str = strtok(sibling_list, ",");
218062306a36Sopenharmony_ci			while (cpu_str != NULL) {
218162306a36Sopenharmony_ci				int cpu;
218262306a36Sopenharmony_ci
218362306a36Sopenharmony_ci				sscanf(cpu_str, "%d", &cpu);
218462306a36Sopenharmony_ci				CPU_SET_S(cpu, target_cpumask_size, target_cpumask);
218562306a36Sopenharmony_ci				cpu_str = strtok(NULL, ",");
218662306a36Sopenharmony_ci			}
218762306a36Sopenharmony_ci		}
218862306a36Sopenharmony_ci
218962306a36Sopenharmony_ci		for (i = 0; i < get_topo_max_cpus(); ++i) {
219062306a36Sopenharmony_ci			int clos;
219162306a36Sopenharmony_ci
219262306a36Sopenharmony_ci			if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
219362306a36Sopenharmony_ci				continue;
219462306a36Sopenharmony_ci
219562306a36Sopenharmony_ci			if (is_cpu_online(i) != 1)
219662306a36Sopenharmony_ci				continue;
219762306a36Sopenharmony_ci
219862306a36Sopenharmony_ci			set_isst_id(&id, i);
219962306a36Sopenharmony_ci			ret = set_clos_param(&id, 0, 0, 0, 0, 0xff);
220062306a36Sopenharmony_ci			if (ret)
220162306a36Sopenharmony_ci				goto error_disp;
220262306a36Sopenharmony_ci
220362306a36Sopenharmony_ci			ret = set_clos_param(&id, 1, 15, 15, 0, 0xff);
220462306a36Sopenharmony_ci			if (ret)
220562306a36Sopenharmony_ci				goto error_disp;
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci			ret = set_clos_param(&id, 2, 15, 15, 0, 0xff);
220862306a36Sopenharmony_ci			if (ret)
220962306a36Sopenharmony_ci				goto error_disp;
221062306a36Sopenharmony_ci
221162306a36Sopenharmony_ci			ret = set_clos_param(&id, 3, 15, 15, 0, 0xff);
221262306a36Sopenharmony_ci			if (ret)
221362306a36Sopenharmony_ci				goto error_disp;
221462306a36Sopenharmony_ci
221562306a36Sopenharmony_ci			if (CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
221662306a36Sopenharmony_ci				clos = 0;
221762306a36Sopenharmony_ci			else
221862306a36Sopenharmony_ci				clos = 3;
221962306a36Sopenharmony_ci
222062306a36Sopenharmony_ci			debug_printf("Associate cpu: %d clos: %d\n", i, clos);
222162306a36Sopenharmony_ci			ret = isst_clos_associate(&id, clos);
222262306a36Sopenharmony_ci			if (ret)
222362306a36Sopenharmony_ci				goto error_disp;
222462306a36Sopenharmony_ci		}
222562306a36Sopenharmony_ci		set_isst_id(&id, -1);
222662306a36Sopenharmony_ci		isst_display_result(&id, outf, "turbo-freq --auto", "enable", 0);
222762306a36Sopenharmony_ci	}
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
223062306a36Sopenharmony_ci
223162306a36Sopenharmony_ci	return;
223262306a36Sopenharmony_ci
223362306a36Sopenharmony_cierror_disp:
223462306a36Sopenharmony_ci	isst_display_result(&id, outf, "turbo-freq --auto", "enable", ret);
223562306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
223662306a36Sopenharmony_ci
223762306a36Sopenharmony_ci}
223862306a36Sopenharmony_ci
223962306a36Sopenharmony_cistatic void enable_clos_qos_config(struct isst_id *id, void *arg1, void *arg2, void *arg3,
224062306a36Sopenharmony_ci				   void *arg4)
224162306a36Sopenharmony_ci{
224262306a36Sopenharmony_ci	int ret;
224362306a36Sopenharmony_ci	int status = *(int *)arg4;
224462306a36Sopenharmony_ci
224562306a36Sopenharmony_ci	if (is_skx_based_platform())
224662306a36Sopenharmony_ci		clos_priority_type = 1;
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci	ret = isst_pm_qos_config(id, status, clos_priority_type);
224962306a36Sopenharmony_ci	if (ret)
225062306a36Sopenharmony_ci		isst_display_error_info_message(1, "isst_pm_qos_config failed", 0, 0);
225162306a36Sopenharmony_ci
225262306a36Sopenharmony_ci	if (status)
225362306a36Sopenharmony_ci		isst_display_result(id, outf, "core-power", "enable",
225462306a36Sopenharmony_ci				    ret);
225562306a36Sopenharmony_ci	else
225662306a36Sopenharmony_ci		isst_display_result(id, outf, "core-power", "disable",
225762306a36Sopenharmony_ci				    ret);
225862306a36Sopenharmony_ci}
225962306a36Sopenharmony_ci
226062306a36Sopenharmony_cistatic void set_clos_enable(int arg)
226162306a36Sopenharmony_ci{
226262306a36Sopenharmony_ci	int enable = arg;
226362306a36Sopenharmony_ci
226462306a36Sopenharmony_ci	if (cmd_help) {
226562306a36Sopenharmony_ci		if (enable) {
226662306a36Sopenharmony_ci			fprintf(stderr,
226762306a36Sopenharmony_ci				"Enable core-power for a package/die\n");
226862306a36Sopenharmony_ci			if (!is_skx_based_platform()) {
226962306a36Sopenharmony_ci				fprintf(stderr,
227062306a36Sopenharmony_ci					"\tClos Enable: Specify priority type with [--priority|-p]\n");
227162306a36Sopenharmony_ci				fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n");
227262306a36Sopenharmony_ci			}
227362306a36Sopenharmony_ci		} else {
227462306a36Sopenharmony_ci			fprintf(stderr,
227562306a36Sopenharmony_ci				"Disable core-power: [No command arguments are required]\n");
227662306a36Sopenharmony_ci		}
227762306a36Sopenharmony_ci		exit(0);
227862306a36Sopenharmony_ci	}
227962306a36Sopenharmony_ci
228062306a36Sopenharmony_ci	if (enable && cpufreq_sysfs_present()) {
228162306a36Sopenharmony_ci		fprintf(stderr,
228262306a36Sopenharmony_ci			"cpufreq subsystem and core-power enable will interfere with each other!\n");
228362306a36Sopenharmony_ci	}
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
228662306a36Sopenharmony_ci	if (max_target_cpus)
228762306a36Sopenharmony_ci		for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
228862306a36Sopenharmony_ci						  NULL, NULL, &enable);
228962306a36Sopenharmony_ci	else
229062306a36Sopenharmony_ci		for_each_online_power_domain_in_set(enable_clos_qos_config, NULL,
229162306a36Sopenharmony_ci					       NULL, NULL, &enable);
229262306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
229362306a36Sopenharmony_ci}
229462306a36Sopenharmony_ci
229562306a36Sopenharmony_cistatic void dump_clos_config_for_cpu(struct isst_id *id, void *arg1, void *arg2,
229662306a36Sopenharmony_ci				     void *arg3, void *arg4)
229762306a36Sopenharmony_ci{
229862306a36Sopenharmony_ci	struct isst_clos_config clos_config;
229962306a36Sopenharmony_ci	int ret;
230062306a36Sopenharmony_ci
230162306a36Sopenharmony_ci	ret = isst_pm_get_clos(id, current_clos, &clos_config);
230262306a36Sopenharmony_ci	if (ret)
230362306a36Sopenharmony_ci		isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
230462306a36Sopenharmony_ci	else
230562306a36Sopenharmony_ci		isst_clos_display_information(id, outf, current_clos,
230662306a36Sopenharmony_ci					      &clos_config);
230762306a36Sopenharmony_ci}
230862306a36Sopenharmony_ci
230962306a36Sopenharmony_cistatic void dump_clos_config(int arg)
231062306a36Sopenharmony_ci{
231162306a36Sopenharmony_ci	if (cmd_help) {
231262306a36Sopenharmony_ci		fprintf(stderr,
231362306a36Sopenharmony_ci			"Print Intel Speed Select Technology core power configuration\n");
231462306a36Sopenharmony_ci		fprintf(stderr,
231562306a36Sopenharmony_ci			"\tArguments: [-c | --clos]: Specify clos id\n");
231662306a36Sopenharmony_ci		exit(0);
231762306a36Sopenharmony_ci	}
231862306a36Sopenharmony_ci	if (current_clos < 0 || current_clos > 3) {
231962306a36Sopenharmony_ci		isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
232062306a36Sopenharmony_ci		isst_ctdp_display_information_end(outf);
232162306a36Sopenharmony_ci		exit(0);
232262306a36Sopenharmony_ci	}
232362306a36Sopenharmony_ci
232462306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
232562306a36Sopenharmony_ci	if (max_target_cpus)
232662306a36Sopenharmony_ci		for_each_online_target_cpu_in_set(dump_clos_config_for_cpu,
232762306a36Sopenharmony_ci						  NULL, NULL, NULL, NULL);
232862306a36Sopenharmony_ci	else
232962306a36Sopenharmony_ci		for_each_online_power_domain_in_set(dump_clos_config_for_cpu, NULL,
233062306a36Sopenharmony_ci					       NULL, NULL, NULL);
233162306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
233262306a36Sopenharmony_ci}
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_cistatic void get_clos_info_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
233562306a36Sopenharmony_ci				  void *arg4)
233662306a36Sopenharmony_ci{
233762306a36Sopenharmony_ci	int enable, ret, prio_type;
233862306a36Sopenharmony_ci
233962306a36Sopenharmony_ci	ret = isst_clos_get_clos_information(id, &enable, &prio_type);
234062306a36Sopenharmony_ci	if (ret)
234162306a36Sopenharmony_ci		isst_display_error_info_message(1, "isst_clos_get_info failed", 0, 0);
234262306a36Sopenharmony_ci	else {
234362306a36Sopenharmony_ci		int cp_state, cp_cap;
234462306a36Sopenharmony_ci
234562306a36Sopenharmony_ci		isst_read_pm_config(id, &cp_state, &cp_cap);
234662306a36Sopenharmony_ci		isst_clos_display_clos_information(id, outf, enable, prio_type,
234762306a36Sopenharmony_ci						   cp_state, cp_cap);
234862306a36Sopenharmony_ci	}
234962306a36Sopenharmony_ci}
235062306a36Sopenharmony_ci
235162306a36Sopenharmony_cistatic void dump_clos_info(int arg)
235262306a36Sopenharmony_ci{
235362306a36Sopenharmony_ci	if (cmd_help) {
235462306a36Sopenharmony_ci		fprintf(stderr,
235562306a36Sopenharmony_ci			"Print Intel Speed Select Technology core power information\n");
235662306a36Sopenharmony_ci		fprintf(stderr, "\t Optionally specify targeted cpu id with [--cpu|-c]\n");
235762306a36Sopenharmony_ci		exit(0);
235862306a36Sopenharmony_ci	}
235962306a36Sopenharmony_ci
236062306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
236162306a36Sopenharmony_ci	if (max_target_cpus)
236262306a36Sopenharmony_ci		for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL,
236362306a36Sopenharmony_ci						  NULL, NULL, NULL);
236462306a36Sopenharmony_ci	else
236562306a36Sopenharmony_ci		for_each_online_power_domain_in_set(get_clos_info_for_cpu, NULL,
236662306a36Sopenharmony_ci					       NULL, NULL, NULL);
236762306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
236862306a36Sopenharmony_ci
236962306a36Sopenharmony_ci}
237062306a36Sopenharmony_ci
237162306a36Sopenharmony_cistatic void set_clos_config_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
237262306a36Sopenharmony_ci				    void *arg4)
237362306a36Sopenharmony_ci{
237462306a36Sopenharmony_ci	struct isst_clos_config clos_config;
237562306a36Sopenharmony_ci	int ret;
237662306a36Sopenharmony_ci
237762306a36Sopenharmony_ci	if (id->cpu < 0)
237862306a36Sopenharmony_ci		return;
237962306a36Sopenharmony_ci
238062306a36Sopenharmony_ci	clos_config.epp = clos_epp;
238162306a36Sopenharmony_ci	clos_config.clos_prop_prio = clos_prop_prio;
238262306a36Sopenharmony_ci	clos_config.clos_min = clos_min;
238362306a36Sopenharmony_ci	clos_config.clos_max = clos_max;
238462306a36Sopenharmony_ci	clos_config.clos_desired = clos_desired;
238562306a36Sopenharmony_ci	ret = isst_set_clos(id, current_clos, &clos_config);
238662306a36Sopenharmony_ci	if (ret)
238762306a36Sopenharmony_ci		isst_display_error_info_message(1, "isst_set_clos failed", 0, 0);
238862306a36Sopenharmony_ci	else
238962306a36Sopenharmony_ci		isst_display_result(id, outf, "core-power", "config", ret);
239062306a36Sopenharmony_ci}
239162306a36Sopenharmony_ci
239262306a36Sopenharmony_cistatic void set_clos_config(int arg)
239362306a36Sopenharmony_ci{
239462306a36Sopenharmony_ci	if (cmd_help) {
239562306a36Sopenharmony_ci		fprintf(stderr,
239662306a36Sopenharmony_ci			"Set core-power configuration for one of the four clos ids\n");
239762306a36Sopenharmony_ci		fprintf(stderr,
239862306a36Sopenharmony_ci			"\tSpecify targeted clos id with [--clos|-c]\n");
239962306a36Sopenharmony_ci		if (!is_skx_based_platform()) {
240062306a36Sopenharmony_ci			fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n");
240162306a36Sopenharmony_ci			fprintf(stderr,
240262306a36Sopenharmony_ci				"\tSpecify clos Proportional Priority [--weight|-w]\n");
240362306a36Sopenharmony_ci		}
240462306a36Sopenharmony_ci		fprintf(stderr, "\tSpecify clos min in MHz with [--min|-n]\n");
240562306a36Sopenharmony_ci		fprintf(stderr, "\tSpecify clos max in MHz with [--max|-m]\n");
240662306a36Sopenharmony_ci		exit(0);
240762306a36Sopenharmony_ci	}
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci	if (current_clos < 0 || current_clos > 3) {
241062306a36Sopenharmony_ci		isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
241162306a36Sopenharmony_ci		exit(0);
241262306a36Sopenharmony_ci	}
241362306a36Sopenharmony_ci	if (!is_skx_based_platform() && (clos_epp < 0 || clos_epp > 0x0F)) {
241462306a36Sopenharmony_ci		fprintf(stderr, "clos epp is not specified or invalid, default: 0\n");
241562306a36Sopenharmony_ci		clos_epp = 0;
241662306a36Sopenharmony_ci	}
241762306a36Sopenharmony_ci	if (!is_skx_based_platform() && (clos_prop_prio < 0 || clos_prop_prio > 0x0F)) {
241862306a36Sopenharmony_ci		fprintf(stderr,
241962306a36Sopenharmony_ci			"clos frequency weight is not specified or invalid, default: 0\n");
242062306a36Sopenharmony_ci		clos_prop_prio = 0;
242162306a36Sopenharmony_ci	}
242262306a36Sopenharmony_ci	if (clos_min < 0) {
242362306a36Sopenharmony_ci		fprintf(stderr, "clos min is not specified, default: 0\n");
242462306a36Sopenharmony_ci		clos_min = 0;
242562306a36Sopenharmony_ci	}
242662306a36Sopenharmony_ci	if (clos_max < 0) {
242762306a36Sopenharmony_ci		fprintf(stderr, "clos max is not specified, default: Max frequency (ratio 0xff)\n");
242862306a36Sopenharmony_ci		clos_max = 0xff;
242962306a36Sopenharmony_ci	}
243062306a36Sopenharmony_ci	if (clos_desired) {
243162306a36Sopenharmony_ci		fprintf(stderr, "clos desired is not supported on this platform\n");
243262306a36Sopenharmony_ci		clos_desired = 0x00;
243362306a36Sopenharmony_ci	}
243462306a36Sopenharmony_ci
243562306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
243662306a36Sopenharmony_ci	if (max_target_cpus)
243762306a36Sopenharmony_ci		for_each_online_target_cpu_in_set(set_clos_config_for_cpu, NULL,
243862306a36Sopenharmony_ci						  NULL, NULL, NULL);
243962306a36Sopenharmony_ci	else
244062306a36Sopenharmony_ci		for_each_online_power_domain_in_set(set_clos_config_for_cpu, NULL,
244162306a36Sopenharmony_ci					       NULL, NULL, NULL);
244262306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
244362306a36Sopenharmony_ci}
244462306a36Sopenharmony_ci
244562306a36Sopenharmony_cistatic void set_clos_assoc_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
244662306a36Sopenharmony_ci				   void *arg4)
244762306a36Sopenharmony_ci{
244862306a36Sopenharmony_ci	int ret;
244962306a36Sopenharmony_ci
245062306a36Sopenharmony_ci	ret = isst_clos_associate(id, current_clos);
245162306a36Sopenharmony_ci	if (ret)
245262306a36Sopenharmony_ci		debug_printf("isst_clos_associate failed");
245362306a36Sopenharmony_ci	else
245462306a36Sopenharmony_ci		isst_display_result(id, outf, "core-power", "assoc", ret);
245562306a36Sopenharmony_ci}
245662306a36Sopenharmony_ci
245762306a36Sopenharmony_cistatic void set_clos_assoc(int arg)
245862306a36Sopenharmony_ci{
245962306a36Sopenharmony_ci	if (cmd_help) {
246062306a36Sopenharmony_ci		fprintf(stderr, "Associate a clos id to a CPU\n");
246162306a36Sopenharmony_ci		fprintf(stderr,
246262306a36Sopenharmony_ci			"\tSpecify targeted clos id with [--clos|-c]\n");
246362306a36Sopenharmony_ci		fprintf(stderr,
246462306a36Sopenharmony_ci			"\tFor example to associate clos 1 to CPU 0: issue\n");
246562306a36Sopenharmony_ci		fprintf(stderr,
246662306a36Sopenharmony_ci			"\tintel-speed-select --cpu 0 core-power assoc --clos 1\n");
246762306a36Sopenharmony_ci		exit(0);
246862306a36Sopenharmony_ci	}
246962306a36Sopenharmony_ci
247062306a36Sopenharmony_ci	if (current_clos < 0 || current_clos > 3) {
247162306a36Sopenharmony_ci		isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
247262306a36Sopenharmony_ci		exit(0);
247362306a36Sopenharmony_ci	}
247462306a36Sopenharmony_ci
247562306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
247662306a36Sopenharmony_ci
247762306a36Sopenharmony_ci	if (max_target_cpus)
247862306a36Sopenharmony_ci		for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL,
247962306a36Sopenharmony_ci						  NULL, NULL, NULL);
248062306a36Sopenharmony_ci	else {
248162306a36Sopenharmony_ci		isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0);
248262306a36Sopenharmony_ci	}
248362306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
248462306a36Sopenharmony_ci}
248562306a36Sopenharmony_ci
248662306a36Sopenharmony_cistatic void get_clos_assoc_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
248762306a36Sopenharmony_ci				   void *arg4)
248862306a36Sopenharmony_ci{
248962306a36Sopenharmony_ci	int clos, ret;
249062306a36Sopenharmony_ci
249162306a36Sopenharmony_ci	ret = isst_clos_get_assoc_status(id, &clos);
249262306a36Sopenharmony_ci	if (ret)
249362306a36Sopenharmony_ci		isst_display_error_info_message(1, "isst_clos_get_assoc_status failed", 0, 0);
249462306a36Sopenharmony_ci	else
249562306a36Sopenharmony_ci		isst_clos_display_assoc_information(id, outf, clos);
249662306a36Sopenharmony_ci}
249762306a36Sopenharmony_ci
249862306a36Sopenharmony_cistatic void get_clos_assoc(int arg)
249962306a36Sopenharmony_ci{
250062306a36Sopenharmony_ci	if (cmd_help) {
250162306a36Sopenharmony_ci		fprintf(stderr, "Get associate clos id to a CPU\n");
250262306a36Sopenharmony_ci		fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n");
250362306a36Sopenharmony_ci		exit(0);
250462306a36Sopenharmony_ci	}
250562306a36Sopenharmony_ci
250662306a36Sopenharmony_ci	if (!max_target_cpus) {
250762306a36Sopenharmony_ci		isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0);
250862306a36Sopenharmony_ci		exit(0);
250962306a36Sopenharmony_ci	}
251062306a36Sopenharmony_ci
251162306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
251262306a36Sopenharmony_ci	for_each_online_target_cpu_in_set(get_clos_assoc_for_cpu, NULL,
251362306a36Sopenharmony_ci					  NULL, NULL, NULL);
251462306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
251562306a36Sopenharmony_ci}
251662306a36Sopenharmony_ci
251762306a36Sopenharmony_cistatic void set_turbo_mode_for_cpu(struct isst_id *id, int status)
251862306a36Sopenharmony_ci{
251962306a36Sopenharmony_ci	int base_freq;
252062306a36Sopenharmony_ci
252162306a36Sopenharmony_ci	if (status) {
252262306a36Sopenharmony_ci		base_freq = get_cpufreq_base_freq(id->cpu);
252362306a36Sopenharmony_ci		set_cpufreq_scaling_min_max(id->cpu, 1, base_freq);
252462306a36Sopenharmony_ci	} else {
252562306a36Sopenharmony_ci		set_scaling_max_to_cpuinfo_max(id);
252662306a36Sopenharmony_ci	}
252762306a36Sopenharmony_ci
252862306a36Sopenharmony_ci	if (status) {
252962306a36Sopenharmony_ci		isst_display_result(id, outf, "turbo-mode", "enable", 0);
253062306a36Sopenharmony_ci	} else {
253162306a36Sopenharmony_ci		isst_display_result(id, outf, "turbo-mode", "disable", 0);
253262306a36Sopenharmony_ci	}
253362306a36Sopenharmony_ci}
253462306a36Sopenharmony_ci
253562306a36Sopenharmony_cistatic void set_turbo_mode(int arg)
253662306a36Sopenharmony_ci{
253762306a36Sopenharmony_ci	int i, enable = arg;
253862306a36Sopenharmony_ci	struct isst_id id;
253962306a36Sopenharmony_ci
254062306a36Sopenharmony_ci	if (cmd_help) {
254162306a36Sopenharmony_ci		if (enable)
254262306a36Sopenharmony_ci			fprintf(stderr, "Set turbo mode enable\n");
254362306a36Sopenharmony_ci		else
254462306a36Sopenharmony_ci			fprintf(stderr, "Set turbo mode disable\n");
254562306a36Sopenharmony_ci		exit(0);
254662306a36Sopenharmony_ci	}
254762306a36Sopenharmony_ci
254862306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
254962306a36Sopenharmony_ci
255062306a36Sopenharmony_ci	for (i = 0; i < topo_max_cpus; ++i) {
255162306a36Sopenharmony_ci		int online;
255262306a36Sopenharmony_ci
255362306a36Sopenharmony_ci		if (i)
255462306a36Sopenharmony_ci			online = parse_int_file(
255562306a36Sopenharmony_ci				1, "/sys/devices/system/cpu/cpu%d/online", i);
255662306a36Sopenharmony_ci		else
255762306a36Sopenharmony_ci			online =
255862306a36Sopenharmony_ci				1; /* online entry for CPU 0 needs some special configs */
255962306a36Sopenharmony_ci
256062306a36Sopenharmony_ci		if (online) {
256162306a36Sopenharmony_ci			set_isst_id(&id, i);
256262306a36Sopenharmony_ci			set_turbo_mode_for_cpu(&id, enable);
256362306a36Sopenharmony_ci		}
256462306a36Sopenharmony_ci
256562306a36Sopenharmony_ci	}
256662306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
256762306a36Sopenharmony_ci}
256862306a36Sopenharmony_ci
256962306a36Sopenharmony_cistatic void get_set_trl(struct isst_id *id, void *arg1, void *arg2, void *arg3,
257062306a36Sopenharmony_ci			void *arg4)
257162306a36Sopenharmony_ci{
257262306a36Sopenharmony_ci	unsigned long long trl;
257362306a36Sopenharmony_ci	int set = *(int *)arg4;
257462306a36Sopenharmony_ci	int ret;
257562306a36Sopenharmony_ci
257662306a36Sopenharmony_ci	if (set && !fact_trl) {
257762306a36Sopenharmony_ci		isst_display_error_info_message(1, "Invalid TRL. Specify with [-t|--trl]", 0, 0);
257862306a36Sopenharmony_ci		exit(0);
257962306a36Sopenharmony_ci	}
258062306a36Sopenharmony_ci
258162306a36Sopenharmony_ci	if (set) {
258262306a36Sopenharmony_ci		ret = isst_set_trl(id, fact_trl);
258362306a36Sopenharmony_ci		isst_display_result(id, outf, "turbo-mode", "set-trl", ret);
258462306a36Sopenharmony_ci		return;
258562306a36Sopenharmony_ci	}
258662306a36Sopenharmony_ci
258762306a36Sopenharmony_ci	ret = isst_get_trl(id, &trl);
258862306a36Sopenharmony_ci	if (ret)
258962306a36Sopenharmony_ci		isst_display_result(id, outf, "turbo-mode", "get-trl", ret);
259062306a36Sopenharmony_ci	else
259162306a36Sopenharmony_ci		isst_trl_display_information(id, outf, trl);
259262306a36Sopenharmony_ci}
259362306a36Sopenharmony_ci
259462306a36Sopenharmony_cistatic void process_trl(int arg)
259562306a36Sopenharmony_ci{
259662306a36Sopenharmony_ci	if (cmd_help) {
259762306a36Sopenharmony_ci		if (arg) {
259862306a36Sopenharmony_ci			fprintf(stderr, "Set TRL (turbo ratio limits)\n");
259962306a36Sopenharmony_ci			fprintf(stderr, "\t t|--trl: Specify turbo ratio limit for setting TRL\n");
260062306a36Sopenharmony_ci		} else {
260162306a36Sopenharmony_ci			fprintf(stderr, "Get TRL (turbo ratio limits)\n");
260262306a36Sopenharmony_ci		}
260362306a36Sopenharmony_ci		exit(0);
260462306a36Sopenharmony_ci	}
260562306a36Sopenharmony_ci
260662306a36Sopenharmony_ci	isst_ctdp_display_information_start(outf);
260762306a36Sopenharmony_ci	if (max_target_cpus)
260862306a36Sopenharmony_ci		for_each_online_target_cpu_in_set(get_set_trl, NULL,
260962306a36Sopenharmony_ci						  NULL, NULL, &arg);
261062306a36Sopenharmony_ci	else
261162306a36Sopenharmony_ci		for_each_online_power_domain_in_set(get_set_trl, NULL,
261262306a36Sopenharmony_ci					       NULL, NULL, &arg);
261362306a36Sopenharmony_ci	isst_ctdp_display_information_end(outf);
261462306a36Sopenharmony_ci}
261562306a36Sopenharmony_ci
261662306a36Sopenharmony_cistatic struct process_cmd_struct clx_n_cmds[] = {
261762306a36Sopenharmony_ci	{ "perf-profile", "info", dump_isst_config, 0 },
261862306a36Sopenharmony_ci	{ "base-freq", "info", dump_pbf_config, 0 },
261962306a36Sopenharmony_ci	{ "base-freq", "enable", set_pbf_enable, 1 },
262062306a36Sopenharmony_ci	{ "base-freq", "disable", set_pbf_enable, 0 },
262162306a36Sopenharmony_ci	{ NULL, NULL, NULL, 0 }
262262306a36Sopenharmony_ci};
262362306a36Sopenharmony_ci
262462306a36Sopenharmony_cistatic struct process_cmd_struct isst_cmds[] = {
262562306a36Sopenharmony_ci	{ "perf-profile", "get-lock-status", get_tdp_locked, 0 },
262662306a36Sopenharmony_ci	{ "perf-profile", "get-config-levels", get_tdp_levels, 0 },
262762306a36Sopenharmony_ci	{ "perf-profile", "get-config-version", get_tdp_version, 0 },
262862306a36Sopenharmony_ci	{ "perf-profile", "get-config-enabled", get_tdp_enabled, 0 },
262962306a36Sopenharmony_ci	{ "perf-profile", "get-config-current-level", get_tdp_current_level,
263062306a36Sopenharmony_ci	 0 },
263162306a36Sopenharmony_ci	{ "perf-profile", "set-config-level", set_tdp_level, 0 },
263262306a36Sopenharmony_ci	{ "perf-profile", "info", dump_isst_config, 0 },
263362306a36Sopenharmony_ci	{ "base-freq", "info", dump_pbf_config, 0 },
263462306a36Sopenharmony_ci	{ "base-freq", "enable", set_pbf_enable, 1 },
263562306a36Sopenharmony_ci	{ "base-freq", "disable", set_pbf_enable, 0 },
263662306a36Sopenharmony_ci	{ "turbo-freq", "info", dump_fact_config, 0 },
263762306a36Sopenharmony_ci	{ "turbo-freq", "enable", set_fact_enable, 1 },
263862306a36Sopenharmony_ci	{ "turbo-freq", "disable", set_fact_enable, 0 },
263962306a36Sopenharmony_ci	{ "core-power", "info", dump_clos_info, 0 },
264062306a36Sopenharmony_ci	{ "core-power", "enable", set_clos_enable, 1 },
264162306a36Sopenharmony_ci	{ "core-power", "disable", set_clos_enable, 0 },
264262306a36Sopenharmony_ci	{ "core-power", "config", set_clos_config, 0 },
264362306a36Sopenharmony_ci	{ "core-power", "get-config", dump_clos_config, 0 },
264462306a36Sopenharmony_ci	{ "core-power", "assoc", set_clos_assoc, 0 },
264562306a36Sopenharmony_ci	{ "core-power", "get-assoc", get_clos_assoc, 0 },
264662306a36Sopenharmony_ci	{ "turbo-mode", "enable", set_turbo_mode, 0 },
264762306a36Sopenharmony_ci	{ "turbo-mode", "disable", set_turbo_mode, 1 },
264862306a36Sopenharmony_ci	{ "turbo-mode", "get-trl", process_trl, 0 },
264962306a36Sopenharmony_ci	{ "turbo-mode", "set-trl", process_trl, 1 },
265062306a36Sopenharmony_ci	{ NULL, NULL, NULL }
265162306a36Sopenharmony_ci};
265262306a36Sopenharmony_ci
265362306a36Sopenharmony_ci/*
265462306a36Sopenharmony_ci * parse cpuset with following syntax
265562306a36Sopenharmony_ci * 1,2,4..6,8-10 and set bits in cpu_subset
265662306a36Sopenharmony_ci */
265762306a36Sopenharmony_civoid parse_cpu_command(char *optarg)
265862306a36Sopenharmony_ci{
265962306a36Sopenharmony_ci	unsigned int start, end, invalid_count;
266062306a36Sopenharmony_ci	char *next;
266162306a36Sopenharmony_ci
266262306a36Sopenharmony_ci	next = optarg;
266362306a36Sopenharmony_ci	invalid_count = 0;
266462306a36Sopenharmony_ci
266562306a36Sopenharmony_ci	while (next && *next) {
266662306a36Sopenharmony_ci		if (*next == '-') /* no negative cpu numbers */
266762306a36Sopenharmony_ci			goto error;
266862306a36Sopenharmony_ci
266962306a36Sopenharmony_ci		start = strtoul(next, &next, 10);
267062306a36Sopenharmony_ci
267162306a36Sopenharmony_ci		if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
267262306a36Sopenharmony_ci			target_cpus[max_target_cpus++] = start;
267362306a36Sopenharmony_ci		else
267462306a36Sopenharmony_ci			invalid_count = 1;
267562306a36Sopenharmony_ci
267662306a36Sopenharmony_ci		if (*next == '\0')
267762306a36Sopenharmony_ci			break;
267862306a36Sopenharmony_ci
267962306a36Sopenharmony_ci		if (*next == ',') {
268062306a36Sopenharmony_ci			next += 1;
268162306a36Sopenharmony_ci			continue;
268262306a36Sopenharmony_ci		}
268362306a36Sopenharmony_ci
268462306a36Sopenharmony_ci		if (*next == '-') {
268562306a36Sopenharmony_ci			next += 1; /* start range */
268662306a36Sopenharmony_ci		} else if (*next == '.') {
268762306a36Sopenharmony_ci			next += 1;
268862306a36Sopenharmony_ci			if (*next == '.')
268962306a36Sopenharmony_ci				next += 1; /* start range */
269062306a36Sopenharmony_ci			else
269162306a36Sopenharmony_ci				goto error;
269262306a36Sopenharmony_ci		}
269362306a36Sopenharmony_ci
269462306a36Sopenharmony_ci		end = strtoul(next, &next, 10);
269562306a36Sopenharmony_ci		if (end <= start)
269662306a36Sopenharmony_ci			goto error;
269762306a36Sopenharmony_ci
269862306a36Sopenharmony_ci		while (++start <= end) {
269962306a36Sopenharmony_ci			if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
270062306a36Sopenharmony_ci				target_cpus[max_target_cpus++] = start;
270162306a36Sopenharmony_ci			else
270262306a36Sopenharmony_ci				invalid_count = 1;
270362306a36Sopenharmony_ci		}
270462306a36Sopenharmony_ci
270562306a36Sopenharmony_ci		if (*next == ',')
270662306a36Sopenharmony_ci			next += 1;
270762306a36Sopenharmony_ci		else if (*next != '\0')
270862306a36Sopenharmony_ci			goto error;
270962306a36Sopenharmony_ci	}
271062306a36Sopenharmony_ci
271162306a36Sopenharmony_ci	if (invalid_count) {
271262306a36Sopenharmony_ci		isst_ctdp_display_information_start(outf);
271362306a36Sopenharmony_ci		isst_display_error_info_message(1, "Too many CPUs in one request: max is", 1, MAX_CPUS_IN_ONE_REQ - 1);
271462306a36Sopenharmony_ci		isst_ctdp_display_information_end(outf);
271562306a36Sopenharmony_ci		exit(-1);
271662306a36Sopenharmony_ci	}
271762306a36Sopenharmony_ci
271862306a36Sopenharmony_ci#ifdef DEBUG
271962306a36Sopenharmony_ci	{
272062306a36Sopenharmony_ci		int i;
272162306a36Sopenharmony_ci
272262306a36Sopenharmony_ci		for (i = 0; i < max_target_cpus; ++i)
272362306a36Sopenharmony_ci			printf("cpu [%d] in arg\n", target_cpus[i]);
272462306a36Sopenharmony_ci	}
272562306a36Sopenharmony_ci#endif
272662306a36Sopenharmony_ci	return;
272762306a36Sopenharmony_ci
272862306a36Sopenharmony_cierror:
272962306a36Sopenharmony_ci	fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);
273062306a36Sopenharmony_ci	exit(-1);
273162306a36Sopenharmony_ci}
273262306a36Sopenharmony_ci
273362306a36Sopenharmony_cistatic void parse_cmd_args(int argc, int start, char **argv)
273462306a36Sopenharmony_ci{
273562306a36Sopenharmony_ci	int opt;
273662306a36Sopenharmony_ci	int option_index;
273762306a36Sopenharmony_ci
273862306a36Sopenharmony_ci	static struct option long_options[] = {
273962306a36Sopenharmony_ci		{ "bucket", required_argument, 0, 'b' },
274062306a36Sopenharmony_ci		{ "level", required_argument, 0, 'l' },
274162306a36Sopenharmony_ci		{ "online", required_argument, 0, 'o' },
274262306a36Sopenharmony_ci		{ "trl-type", required_argument, 0, 'r' },
274362306a36Sopenharmony_ci		{ "trl", required_argument, 0, 't' },
274462306a36Sopenharmony_ci		{ "help", no_argument, 0, 'h' },
274562306a36Sopenharmony_ci		{ "clos", required_argument, 0, 'c' },
274662306a36Sopenharmony_ci		{ "desired", required_argument, 0, 'd' },
274762306a36Sopenharmony_ci		{ "epp", required_argument, 0, 'e' },
274862306a36Sopenharmony_ci		{ "min", required_argument, 0, 'n' },
274962306a36Sopenharmony_ci		{ "max", required_argument, 0, 'm' },
275062306a36Sopenharmony_ci		{ "priority", required_argument, 0, 'p' },
275162306a36Sopenharmony_ci		{ "weight", required_argument, 0, 'w' },
275262306a36Sopenharmony_ci		{ "auto", no_argument, 0, 'a' },
275362306a36Sopenharmony_ci		{ 0, 0, 0, 0 }
275462306a36Sopenharmony_ci	};
275562306a36Sopenharmony_ci
275662306a36Sopenharmony_ci	option_index = start;
275762306a36Sopenharmony_ci
275862306a36Sopenharmony_ci	optind = start + 1;
275962306a36Sopenharmony_ci	while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:r:hoa",
276062306a36Sopenharmony_ci				  long_options, &option_index)) != -1) {
276162306a36Sopenharmony_ci		switch (opt) {
276262306a36Sopenharmony_ci		case 'a':
276362306a36Sopenharmony_ci			auto_mode = 1;
276462306a36Sopenharmony_ci			break;
276562306a36Sopenharmony_ci		case 'b':
276662306a36Sopenharmony_ci			fact_bucket = atoi(optarg);
276762306a36Sopenharmony_ci			break;
276862306a36Sopenharmony_ci		case 'h':
276962306a36Sopenharmony_ci			cmd_help = 1;
277062306a36Sopenharmony_ci			break;
277162306a36Sopenharmony_ci		case 'l':
277262306a36Sopenharmony_ci			tdp_level = atoi(optarg);
277362306a36Sopenharmony_ci			break;
277462306a36Sopenharmony_ci		case 'o':
277562306a36Sopenharmony_ci			force_online_offline = 1;
277662306a36Sopenharmony_ci			break;
277762306a36Sopenharmony_ci		case 't':
277862306a36Sopenharmony_ci			sscanf(optarg, "0x%llx", &fact_trl);
277962306a36Sopenharmony_ci			break;
278062306a36Sopenharmony_ci		case 'r':
278162306a36Sopenharmony_ci			if (!strncmp(optarg, "sse", 3)) {
278262306a36Sopenharmony_ci				fact_avx = 0x01;
278362306a36Sopenharmony_ci			} else if (!strncmp(optarg, "avx2", 4)) {
278462306a36Sopenharmony_ci				fact_avx = 0x02;
278562306a36Sopenharmony_ci			} else if (!strncmp(optarg, "avx512", 6)) {
278662306a36Sopenharmony_ci				fact_avx = 0x04;
278762306a36Sopenharmony_ci			} else {
278862306a36Sopenharmony_ci				fprintf(outf, "Invalid sse,avx options\n");
278962306a36Sopenharmony_ci				exit(1);
279062306a36Sopenharmony_ci			}
279162306a36Sopenharmony_ci			break;
279262306a36Sopenharmony_ci		/* CLOS related */
279362306a36Sopenharmony_ci		case 'c':
279462306a36Sopenharmony_ci			current_clos = atoi(optarg);
279562306a36Sopenharmony_ci			break;
279662306a36Sopenharmony_ci		case 'd':
279762306a36Sopenharmony_ci			clos_desired = atoi(optarg);
279862306a36Sopenharmony_ci			clos_desired /= isst_get_disp_freq_multiplier();
279962306a36Sopenharmony_ci			break;
280062306a36Sopenharmony_ci		case 'e':
280162306a36Sopenharmony_ci			clos_epp = atoi(optarg);
280262306a36Sopenharmony_ci			if (is_skx_based_platform()) {
280362306a36Sopenharmony_ci				isst_display_error_info_message(1, "epp can't be specified on this platform", 0, 0);
280462306a36Sopenharmony_ci				exit(0);
280562306a36Sopenharmony_ci			}
280662306a36Sopenharmony_ci			break;
280762306a36Sopenharmony_ci		case 'n':
280862306a36Sopenharmony_ci			clos_min = atoi(optarg);
280962306a36Sopenharmony_ci			clos_min /= isst_get_disp_freq_multiplier();
281062306a36Sopenharmony_ci			break;
281162306a36Sopenharmony_ci		case 'm':
281262306a36Sopenharmony_ci			clos_max = atoi(optarg);
281362306a36Sopenharmony_ci			clos_max /= isst_get_disp_freq_multiplier();
281462306a36Sopenharmony_ci			break;
281562306a36Sopenharmony_ci		case 'p':
281662306a36Sopenharmony_ci			clos_priority_type = atoi(optarg);
281762306a36Sopenharmony_ci			if (is_skx_based_platform() && !clos_priority_type) {
281862306a36Sopenharmony_ci				isst_display_error_info_message(1, "Invalid clos priority type: proportional for this platform", 0, 0);
281962306a36Sopenharmony_ci				exit(0);
282062306a36Sopenharmony_ci			}
282162306a36Sopenharmony_ci			break;
282262306a36Sopenharmony_ci		case 'w':
282362306a36Sopenharmony_ci			clos_prop_prio = atoi(optarg);
282462306a36Sopenharmony_ci			if (is_skx_based_platform()) {
282562306a36Sopenharmony_ci				isst_display_error_info_message(1, "weight can't be specified on this platform", 0, 0);
282662306a36Sopenharmony_ci				exit(0);
282762306a36Sopenharmony_ci			}
282862306a36Sopenharmony_ci			break;
282962306a36Sopenharmony_ci		default:
283062306a36Sopenharmony_ci			printf("Unknown option: ignore\n");
283162306a36Sopenharmony_ci		}
283262306a36Sopenharmony_ci	}
283362306a36Sopenharmony_ci
283462306a36Sopenharmony_ci	if (argv[optind])
283562306a36Sopenharmony_ci		printf("Garbage at the end of command: ignore\n");
283662306a36Sopenharmony_ci}
283762306a36Sopenharmony_ci
283862306a36Sopenharmony_cistatic void isst_help(void)
283962306a36Sopenharmony_ci{
284062306a36Sopenharmony_ci	printf("perf-profile:\tAn architectural mechanism that allows multiple optimized \n\
284162306a36Sopenharmony_ci		performance profiles per system via static and/or dynamic\n\
284262306a36Sopenharmony_ci		adjustment of core count, workload, Tjmax, and\n\
284362306a36Sopenharmony_ci		TDP, etc.\n");
284462306a36Sopenharmony_ci	printf("\nCommands : For feature=perf-profile\n");
284562306a36Sopenharmony_ci	printf("\tinfo\n");
284662306a36Sopenharmony_ci
284762306a36Sopenharmony_ci	if (!is_clx_n_platform()) {
284862306a36Sopenharmony_ci		printf("\tget-lock-status\n");
284962306a36Sopenharmony_ci		printf("\tget-config-levels\n");
285062306a36Sopenharmony_ci		printf("\tget-config-version\n");
285162306a36Sopenharmony_ci		printf("\tget-config-enabled\n");
285262306a36Sopenharmony_ci		printf("\tget-config-current-level\n");
285362306a36Sopenharmony_ci		printf("\tset-config-level\n");
285462306a36Sopenharmony_ci	}
285562306a36Sopenharmony_ci}
285662306a36Sopenharmony_ci
285762306a36Sopenharmony_cistatic void pbf_help(void)
285862306a36Sopenharmony_ci{
285962306a36Sopenharmony_ci	printf("base-freq:\tEnables users to increase guaranteed base frequency\n\
286062306a36Sopenharmony_ci		on certain cores (high priority cores) in exchange for lower\n\
286162306a36Sopenharmony_ci		base frequency on remaining cores (low priority cores).\n");
286262306a36Sopenharmony_ci	printf("\tcommand : info\n");
286362306a36Sopenharmony_ci	printf("\tcommand : enable\n");
286462306a36Sopenharmony_ci	printf("\tcommand : disable\n");
286562306a36Sopenharmony_ci}
286662306a36Sopenharmony_ci
286762306a36Sopenharmony_cistatic void fact_help(void)
286862306a36Sopenharmony_ci{
286962306a36Sopenharmony_ci	printf("turbo-freq:\tEnables the ability to set different turbo ratio\n\
287062306a36Sopenharmony_ci		limits to cores based on priority.\n");
287162306a36Sopenharmony_ci	printf("\nCommand: For feature=turbo-freq\n");
287262306a36Sopenharmony_ci	printf("\tcommand : info\n");
287362306a36Sopenharmony_ci	printf("\tcommand : enable\n");
287462306a36Sopenharmony_ci	printf("\tcommand : disable\n");
287562306a36Sopenharmony_ci}
287662306a36Sopenharmony_ci
287762306a36Sopenharmony_cistatic void turbo_mode_help(void)
287862306a36Sopenharmony_ci{
287962306a36Sopenharmony_ci	printf("turbo-mode:\tEnables users to enable/disable turbo mode by adjusting frequency settings. Also allows to get and set turbo ratio limits (TRL).\n");
288062306a36Sopenharmony_ci	printf("\tcommand : enable\n");
288162306a36Sopenharmony_ci	printf("\tcommand : disable\n");
288262306a36Sopenharmony_ci	printf("\tcommand : get-trl\n");
288362306a36Sopenharmony_ci	printf("\tcommand : set-trl\n");
288462306a36Sopenharmony_ci}
288562306a36Sopenharmony_ci
288662306a36Sopenharmony_ci
288762306a36Sopenharmony_cistatic void core_power_help(void)
288862306a36Sopenharmony_ci{
288962306a36Sopenharmony_ci	printf("core-power:\tInterface that allows user to define per core/tile\n\
289062306a36Sopenharmony_ci		priority.\n");
289162306a36Sopenharmony_ci	printf("\nCommands : For feature=core-power\n");
289262306a36Sopenharmony_ci	printf("\tinfo\n");
289362306a36Sopenharmony_ci	printf("\tenable\n");
289462306a36Sopenharmony_ci	printf("\tdisable\n");
289562306a36Sopenharmony_ci	printf("\tconfig\n");
289662306a36Sopenharmony_ci	printf("\tget-config\n");
289762306a36Sopenharmony_ci	printf("\tassoc\n");
289862306a36Sopenharmony_ci	printf("\tget-assoc\n");
289962306a36Sopenharmony_ci}
290062306a36Sopenharmony_ci
290162306a36Sopenharmony_cistruct process_cmd_help_struct {
290262306a36Sopenharmony_ci	char *feature;
290362306a36Sopenharmony_ci	void (*process_fn)(void);
290462306a36Sopenharmony_ci};
290562306a36Sopenharmony_ci
290662306a36Sopenharmony_cistatic struct process_cmd_help_struct isst_help_cmds[] = {
290762306a36Sopenharmony_ci	{ "perf-profile", isst_help },
290862306a36Sopenharmony_ci	{ "base-freq", pbf_help },
290962306a36Sopenharmony_ci	{ "turbo-freq", fact_help },
291062306a36Sopenharmony_ci	{ "core-power", core_power_help },
291162306a36Sopenharmony_ci	{ "turbo-mode", turbo_mode_help },
291262306a36Sopenharmony_ci	{ NULL, NULL }
291362306a36Sopenharmony_ci};
291462306a36Sopenharmony_ci
291562306a36Sopenharmony_cistatic struct process_cmd_help_struct clx_n_help_cmds[] = {
291662306a36Sopenharmony_ci	{ "perf-profile", isst_help },
291762306a36Sopenharmony_ci	{ "base-freq", pbf_help },
291862306a36Sopenharmony_ci	{ NULL, NULL }
291962306a36Sopenharmony_ci};
292062306a36Sopenharmony_ci
292162306a36Sopenharmony_civoid process_command(int argc, char **argv,
292262306a36Sopenharmony_ci		     struct process_cmd_help_struct *help_cmds,
292362306a36Sopenharmony_ci		     struct process_cmd_struct *cmds)
292462306a36Sopenharmony_ci{
292562306a36Sopenharmony_ci	int i = 0, matched = 0;
292662306a36Sopenharmony_ci	char *feature = argv[optind];
292762306a36Sopenharmony_ci	char *cmd = argv[optind + 1];
292862306a36Sopenharmony_ci
292962306a36Sopenharmony_ci	if (!feature || !cmd)
293062306a36Sopenharmony_ci		return;
293162306a36Sopenharmony_ci
293262306a36Sopenharmony_ci	debug_printf("feature name [%s] command [%s]\n", feature, cmd);
293362306a36Sopenharmony_ci	if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) {
293462306a36Sopenharmony_ci		while (help_cmds[i].feature) {
293562306a36Sopenharmony_ci			if (!strcmp(help_cmds[i].feature, feature)) {
293662306a36Sopenharmony_ci				help_cmds[i].process_fn();
293762306a36Sopenharmony_ci				exit(0);
293862306a36Sopenharmony_ci			}
293962306a36Sopenharmony_ci			++i;
294062306a36Sopenharmony_ci		}
294162306a36Sopenharmony_ci	}
294262306a36Sopenharmony_ci
294362306a36Sopenharmony_ci	i = 0;
294462306a36Sopenharmony_ci	while (cmds[i].feature) {
294562306a36Sopenharmony_ci		if (!strcmp(cmds[i].feature, feature) &&
294662306a36Sopenharmony_ci		    !strcmp(cmds[i].command, cmd)) {
294762306a36Sopenharmony_ci			parse_cmd_args(argc, optind + 1, argv);
294862306a36Sopenharmony_ci			cmds[i].process_fn(cmds[i].arg);
294962306a36Sopenharmony_ci			matched = 1;
295062306a36Sopenharmony_ci			break;
295162306a36Sopenharmony_ci		}
295262306a36Sopenharmony_ci		++i;
295362306a36Sopenharmony_ci	}
295462306a36Sopenharmony_ci
295562306a36Sopenharmony_ci	if (!matched)
295662306a36Sopenharmony_ci		fprintf(stderr, "Invalid command\n");
295762306a36Sopenharmony_ci}
295862306a36Sopenharmony_ci
295962306a36Sopenharmony_cistatic void usage(void)
296062306a36Sopenharmony_ci{
296162306a36Sopenharmony_ci	if (is_clx_n_platform()) {
296262306a36Sopenharmony_ci		fprintf(stderr, "\nThere is limited support of Intel Speed Select features on this platform.\n");
296362306a36Sopenharmony_ci		fprintf(stderr, "Everything is pre-configured using BIOS options, this tool can't enable any feature in the hardware.\n\n");
296462306a36Sopenharmony_ci	}
296562306a36Sopenharmony_ci
296662306a36Sopenharmony_ci	printf("\nUsage:\n");
296762306a36Sopenharmony_ci	printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n");
296862306a36Sopenharmony_ci	printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features:\n");
296962306a36Sopenharmony_ci	if (is_clx_n_platform())
297062306a36Sopenharmony_ci		printf("\nFEATURE : [perf-profile|base-freq]\n");
297162306a36Sopenharmony_ci	else
297262306a36Sopenharmony_ci		printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power|turbo-mode]\n");
297362306a36Sopenharmony_ci	printf("\nFor help on each feature, use -h|--help\n");
297462306a36Sopenharmony_ci	printf("\tFor example:  intel-speed-select perf-profile -h\n");
297562306a36Sopenharmony_ci
297662306a36Sopenharmony_ci	printf("\nFor additional help on each command for a feature, use --h|--help\n");
297762306a36Sopenharmony_ci	printf("\tFor example:  intel-speed-select perf-profile get-lock-status -h\n");
297862306a36Sopenharmony_ci	printf("\t\t This will print help for the command \"get-lock-status\" for the feature \"perf-profile\"\n");
297962306a36Sopenharmony_ci
298062306a36Sopenharmony_ci	printf("\nOPTIONS\n");
298162306a36Sopenharmony_ci	printf("\t[-c|--cpu] : logical cpu number\n");
298262306a36Sopenharmony_ci	printf("\t\tDefault: Die scoped for all dies in the system with multiple dies/package\n");
298362306a36Sopenharmony_ci	printf("\t\t\t Or Package scoped for all Packages when each package contains one die\n");
298462306a36Sopenharmony_ci	printf("\t[-d|--debug] : Debug mode\n");
298562306a36Sopenharmony_ci	printf("\t[-f|--format] : output format [json|text]. Default: text\n");
298662306a36Sopenharmony_ci	printf("\t[-h|--help] : Print help\n");
298762306a36Sopenharmony_ci	printf("\t[-i|--info] : Print platform information\n");
298862306a36Sopenharmony_ci	printf("\t[-a|--all-cpus-online] : Force online every CPU in the system\n");
298962306a36Sopenharmony_ci	printf("\t[-o|--out] : Output file\n");
299062306a36Sopenharmony_ci	printf("\t\t\tDefault : stderr\n");
299162306a36Sopenharmony_ci	printf("\t[-p|--pause] : Delay between two mail box commands in milliseconds\n");
299262306a36Sopenharmony_ci	printf("\t[-r|--retry] : Retry count for mail box commands on failure, default 3\n");
299362306a36Sopenharmony_ci	printf("\t[-v|--version] : Print version\n");
299462306a36Sopenharmony_ci	printf("\t[-b|--oob : Start a daemon to process HFI events for perf profile change from Out of Band agent.\n");
299562306a36Sopenharmony_ci	printf("\t[-n|--no-daemon : Don't run as daemon. By default --oob will turn on daemon mode\n");
299662306a36Sopenharmony_ci	printf("\t[-w|--delay : Delay for reading config level state change in OOB poll mode.\n");
299762306a36Sopenharmony_ci	printf("\t[-g|--cgroupv2 : Try to use cgroup v2 CPU isolation instead of CPU online/offline.\n");
299862306a36Sopenharmony_ci	printf("\nResult format\n");
299962306a36Sopenharmony_ci	printf("\tResult display uses a common format for each command:\n");
300062306a36Sopenharmony_ci	printf("\tResults are formatted in text/JSON with\n");
300162306a36Sopenharmony_ci	printf("\t\tPackage, Die, CPU, and command specific results.\n");
300262306a36Sopenharmony_ci
300362306a36Sopenharmony_ci	printf("\nExamples\n");
300462306a36Sopenharmony_ci	printf("\tTo get platform information:\n");
300562306a36Sopenharmony_ci	printf("\t\tintel-speed-select --info\n");
300662306a36Sopenharmony_ci	printf("\tTo get full perf-profile information dump:\n");
300762306a36Sopenharmony_ci	printf("\t\tintel-speed-select perf-profile info\n");
300862306a36Sopenharmony_ci	printf("\tTo get full base-freq information dump:\n");
300962306a36Sopenharmony_ci	printf("\t\tintel-speed-select base-freq info -l 0\n");
301062306a36Sopenharmony_ci	if (!is_clx_n_platform()) {
301162306a36Sopenharmony_ci		printf("\tTo get full turbo-freq information dump:\n");
301262306a36Sopenharmony_ci		printf("\t\tintel-speed-select turbo-freq info -l 0\n");
301362306a36Sopenharmony_ci	}
301462306a36Sopenharmony_ci	exit(1);
301562306a36Sopenharmony_ci}
301662306a36Sopenharmony_ci
301762306a36Sopenharmony_cistatic void print_version(void)
301862306a36Sopenharmony_ci{
301962306a36Sopenharmony_ci	fprintf(outf, "Version %s\n", version_str);
302062306a36Sopenharmony_ci	exit(0);
302162306a36Sopenharmony_ci}
302262306a36Sopenharmony_ci
302362306a36Sopenharmony_cistatic void cmdline(int argc, char **argv)
302462306a36Sopenharmony_ci{
302562306a36Sopenharmony_ci	const char *pathname = "/dev/isst_interface";
302662306a36Sopenharmony_ci	char *ptr;
302762306a36Sopenharmony_ci	FILE *fp;
302862306a36Sopenharmony_ci	int opt, force_cpus_online = 0;
302962306a36Sopenharmony_ci	int option_index = 0;
303062306a36Sopenharmony_ci	int ret;
303162306a36Sopenharmony_ci	int oob_mode = 0;
303262306a36Sopenharmony_ci	int poll_interval = -1;
303362306a36Sopenharmony_ci	int no_daemon = 0;
303462306a36Sopenharmony_ci	int mbox_delay = 0, mbox_retries = 3;
303562306a36Sopenharmony_ci
303662306a36Sopenharmony_ci	static struct option long_options[] = {
303762306a36Sopenharmony_ci		{ "all-cpus-online", no_argument, 0, 'a' },
303862306a36Sopenharmony_ci		{ "cpu", required_argument, 0, 'c' },
303962306a36Sopenharmony_ci		{ "debug", no_argument, 0, 'd' },
304062306a36Sopenharmony_ci		{ "format", required_argument, 0, 'f' },
304162306a36Sopenharmony_ci		{ "help", no_argument, 0, 'h' },
304262306a36Sopenharmony_ci		{ "info", no_argument, 0, 'i' },
304362306a36Sopenharmony_ci		{ "pause", required_argument, 0, 'p' },
304462306a36Sopenharmony_ci		{ "out", required_argument, 0, 'o' },
304562306a36Sopenharmony_ci		{ "retry", required_argument, 0, 'r' },
304662306a36Sopenharmony_ci		{ "version", no_argument, 0, 'v' },
304762306a36Sopenharmony_ci		{ "oob", no_argument, 0, 'b' },
304862306a36Sopenharmony_ci		{ "no-daemon", no_argument, 0, 'n' },
304962306a36Sopenharmony_ci		{ "poll-interval", required_argument, 0, 'w' },
305062306a36Sopenharmony_ci		{ "cgroupv2", required_argument, 0, 'g' },
305162306a36Sopenharmony_ci		{ 0, 0, 0, 0 }
305262306a36Sopenharmony_ci	};
305362306a36Sopenharmony_ci
305462306a36Sopenharmony_ci	if (geteuid() != 0) {
305562306a36Sopenharmony_ci		fprintf(stderr, "Must run as root\n");
305662306a36Sopenharmony_ci		exit(0);
305762306a36Sopenharmony_ci	}
305862306a36Sopenharmony_ci
305962306a36Sopenharmony_ci	ret = update_cpu_model();
306062306a36Sopenharmony_ci	if (ret)
306162306a36Sopenharmony_ci		err(-1, "Invalid CPU model (%d)\n", cpu_model);
306262306a36Sopenharmony_ci	printf("Intel(R) Speed Select Technology\n");
306362306a36Sopenharmony_ci	printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model);
306462306a36Sopenharmony_ci
306562306a36Sopenharmony_ci	if (!is_clx_n_platform()) {
306662306a36Sopenharmony_ci		fp = fopen(pathname, "rb");
306762306a36Sopenharmony_ci		if (!fp) {
306862306a36Sopenharmony_ci			fprintf(stderr, "Intel speed select drivers are not loaded on this system.\n");
306962306a36Sopenharmony_ci			fprintf(stderr, "Verify that kernel config includes CONFIG_INTEL_SPEED_SELECT_INTERFACE.\n");
307062306a36Sopenharmony_ci			fprintf(stderr, "If the config is included then this is not a supported platform.\n");
307162306a36Sopenharmony_ci			exit(0);
307262306a36Sopenharmony_ci		}
307362306a36Sopenharmony_ci		fclose(fp);
307462306a36Sopenharmony_ci	}
307562306a36Sopenharmony_ci
307662306a36Sopenharmony_ci	ret = isst_fill_platform_info();
307762306a36Sopenharmony_ci	if (ret)
307862306a36Sopenharmony_ci		goto out;
307962306a36Sopenharmony_ci
308062306a36Sopenharmony_ci	progname = argv[0];
308162306a36Sopenharmony_ci	while ((opt = getopt_long_only(argc, argv, "+c:df:hio:vabw:ng", long_options,
308262306a36Sopenharmony_ci				       &option_index)) != -1) {
308362306a36Sopenharmony_ci		switch (opt) {
308462306a36Sopenharmony_ci		case 'a':
308562306a36Sopenharmony_ci			force_cpus_online = 1;
308662306a36Sopenharmony_ci			break;
308762306a36Sopenharmony_ci		case 'c':
308862306a36Sopenharmony_ci			parse_cpu_command(optarg);
308962306a36Sopenharmony_ci			break;
309062306a36Sopenharmony_ci		case 'd':
309162306a36Sopenharmony_ci			debug_flag = 1;
309262306a36Sopenharmony_ci			printf("Debug Mode ON\n");
309362306a36Sopenharmony_ci			break;
309462306a36Sopenharmony_ci		case 'f':
309562306a36Sopenharmony_ci			if (!strncmp(optarg, "json", 4))
309662306a36Sopenharmony_ci				out_format_json = 1;
309762306a36Sopenharmony_ci			break;
309862306a36Sopenharmony_ci		case 'h':
309962306a36Sopenharmony_ci			usage();
310062306a36Sopenharmony_ci			break;
310162306a36Sopenharmony_ci		case 'i':
310262306a36Sopenharmony_ci			isst_print_platform_information();
310362306a36Sopenharmony_ci			break;
310462306a36Sopenharmony_ci		case 'o':
310562306a36Sopenharmony_ci			if (outf)
310662306a36Sopenharmony_ci				fclose(outf);
310762306a36Sopenharmony_ci			outf = fopen_or_exit(optarg, "w");
310862306a36Sopenharmony_ci			break;
310962306a36Sopenharmony_ci		case 'p':
311062306a36Sopenharmony_ci			ret = strtol(optarg, &ptr, 10);
311162306a36Sopenharmony_ci			if (!ret)
311262306a36Sopenharmony_ci				fprintf(stderr, "Invalid pause interval, ignore\n");
311362306a36Sopenharmony_ci			else
311462306a36Sopenharmony_ci				mbox_delay = ret;
311562306a36Sopenharmony_ci			break;
311662306a36Sopenharmony_ci		case 'r':
311762306a36Sopenharmony_ci			ret = strtol(optarg, &ptr, 10);
311862306a36Sopenharmony_ci			if (!ret)
311962306a36Sopenharmony_ci				fprintf(stderr, "Invalid retry count, ignore\n");
312062306a36Sopenharmony_ci			else
312162306a36Sopenharmony_ci				mbox_retries = ret;
312262306a36Sopenharmony_ci			break;
312362306a36Sopenharmony_ci		case 'v':
312462306a36Sopenharmony_ci			print_version();
312562306a36Sopenharmony_ci			break;
312662306a36Sopenharmony_ci		case 'b':
312762306a36Sopenharmony_ci			oob_mode = 1;
312862306a36Sopenharmony_ci			break;
312962306a36Sopenharmony_ci		case 'n':
313062306a36Sopenharmony_ci			no_daemon = 1;
313162306a36Sopenharmony_ci			break;
313262306a36Sopenharmony_ci		case 'w':
313362306a36Sopenharmony_ci			ret = strtol(optarg, &ptr, 10);
313462306a36Sopenharmony_ci			if (!ret) {
313562306a36Sopenharmony_ci				fprintf(stderr, "Invalid poll interval count\n");
313662306a36Sopenharmony_ci				exit(0);
313762306a36Sopenharmony_ci			}
313862306a36Sopenharmony_ci			poll_interval = ret;
313962306a36Sopenharmony_ci			break;
314062306a36Sopenharmony_ci		case 'g':
314162306a36Sopenharmony_ci			cgroupv2 = 1;
314262306a36Sopenharmony_ci			break;
314362306a36Sopenharmony_ci		default:
314462306a36Sopenharmony_ci			usage();
314562306a36Sopenharmony_ci		}
314662306a36Sopenharmony_ci	}
314762306a36Sopenharmony_ci
314862306a36Sopenharmony_ci	if (optind > (argc - 2) && !oob_mode) {
314962306a36Sopenharmony_ci		usage();
315062306a36Sopenharmony_ci		exit(0);
315162306a36Sopenharmony_ci	}
315262306a36Sopenharmony_ci
315362306a36Sopenharmony_ci	isst_update_platform_param(ISST_PARAM_MBOX_DELAY, mbox_delay);
315462306a36Sopenharmony_ci	isst_update_platform_param(ISST_PARAM_MBOX_RETRIES, mbox_retries);
315562306a36Sopenharmony_ci
315662306a36Sopenharmony_ci	set_max_cpu_num();
315762306a36Sopenharmony_ci	if (force_cpus_online)
315862306a36Sopenharmony_ci		force_all_cpus_online();
315962306a36Sopenharmony_ci	store_cpu_topology();
316062306a36Sopenharmony_ci	create_cpu_map();
316162306a36Sopenharmony_ci
316262306a36Sopenharmony_ci	if (oob_mode) {
316362306a36Sopenharmony_ci		if (debug_flag)
316462306a36Sopenharmony_ci			fprintf(stderr, "OOB mode is enabled in debug mode\n");
316562306a36Sopenharmony_ci
316662306a36Sopenharmony_ci		ret = isst_daemon(debug_flag, poll_interval, no_daemon);
316762306a36Sopenharmony_ci		if (ret)
316862306a36Sopenharmony_ci			fprintf(stderr, "OOB mode enable failed\n");
316962306a36Sopenharmony_ci		goto out;
317062306a36Sopenharmony_ci	}
317162306a36Sopenharmony_ci
317262306a36Sopenharmony_ci	if (!is_clx_n_platform()) {
317362306a36Sopenharmony_ci		process_command(argc, argv, isst_help_cmds, isst_cmds);
317462306a36Sopenharmony_ci	} else {
317562306a36Sopenharmony_ci		process_command(argc, argv, clx_n_help_cmds, clx_n_cmds);
317662306a36Sopenharmony_ci	}
317762306a36Sopenharmony_ciout:
317862306a36Sopenharmony_ci	free_cpu_set(present_cpumask);
317962306a36Sopenharmony_ci	free_cpu_set(target_cpumask);
318062306a36Sopenharmony_ci}
318162306a36Sopenharmony_ci
318262306a36Sopenharmony_ciint main(int argc, char **argv)
318362306a36Sopenharmony_ci{
318462306a36Sopenharmony_ci	outf = stderr;
318562306a36Sopenharmony_ci	cmdline(argc, argv);
318662306a36Sopenharmony_ci	return 0;
318762306a36Sopenharmony_ci}
3188