xref: /linux/tools/power/x86/intel-speed-select/isst-core-tpmi.c (revision 9d588a1140b9ae211581a7a154d0b806d8cd8238)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Intel Speed Select -- Enumerate and control features for TPMI Interface
4  * Copyright (c) 2022 Intel Corporation.
5  */
6 
7 #include <linux/isst_if.h>
8 #include "isst.h"
9 
tpmi_process_ioctl(int ioctl_no,void * info)10 int tpmi_process_ioctl(int ioctl_no, void *info)
11 {
12 	const char *pathname = "/dev/isst_interface";
13 	int fd;
14 
15 	if (is_debug_enabled()) {
16 		debug_printf("Issue IOCTL: ");
17 		switch (ioctl_no) {
18 		case ISST_IF_CORE_POWER_STATE:
19 			debug_printf("ISST_IF_CORE_POWER_STATE\n");
20 			break;
21 		case ISST_IF_CLOS_PARAM:
22 			debug_printf("ISST_IF_CLOS_PARAM\n");
23 			break;
24 		case ISST_IF_CLOS_ASSOC:
25 			debug_printf("ISST_IF_CLOS_ASSOC\n");
26 			break;
27 		case ISST_IF_PERF_LEVELS:
28 			debug_printf("ISST_IF_PERF_LEVELS\n");
29 			break;
30 		case ISST_IF_PERF_SET_LEVEL:
31 			debug_printf("ISST_IF_PERF_SET_LEVEL\n");
32 			break;
33 		case ISST_IF_PERF_SET_FEATURE:
34 			debug_printf("ISST_IF_PERF_SET_FEATURE\n");
35 			break;
36 		case ISST_IF_GET_PERF_LEVEL_INFO:
37 			debug_printf("ISST_IF_GET_PERF_LEVEL_INFO\n");
38 			break;
39 		case ISST_IF_GET_PERF_LEVEL_CPU_MASK:
40 			debug_printf("ISST_IF_GET_PERF_LEVEL_CPU_MASK\n");
41 			break;
42 		case ISST_IF_GET_BASE_FREQ_INFO:
43 			debug_printf("ISST_IF_GET_BASE_FREQ_INFO\n");
44 			break;
45 		case ISST_IF_GET_BASE_FREQ_CPU_MASK:
46 			debug_printf("ISST_IF_GET_BASE_FREQ_CPU_MASK\n");
47 			break;
48 		case ISST_IF_GET_TURBO_FREQ_INFO:
49 			debug_printf("ISST_IF_GET_TURBO_FREQ_INFO\n");
50 			break;
51 		case ISST_IF_COUNT_TPMI_INSTANCES:
52 			debug_printf("ISST_IF_COUNT_TPMI_INSTANCES\n");
53 			break;
54 		default:
55 			debug_printf("%d\n", ioctl_no);
56 			break;
57 		}
58 	}
59 
60 	fd = open(pathname, O_RDWR);
61 	if (fd < 0)
62 		return -1;
63 
64 	if (ioctl(fd, ioctl_no, info) == -1) {
65 		debug_printf("IOCTL %d Failed\n", ioctl_no);
66 		close(fd);
67 		return -1;
68 	}
69 
70 	close(fd);
71 
72 	return 0;
73 }
74 
tpmi_get_disp_freq_multiplier(void)75 static int tpmi_get_disp_freq_multiplier(void)
76 {
77 	return 1;
78 }
79 
tpmi_get_trl_max_levels(void)80 static int tpmi_get_trl_max_levels(void)
81 {
82 	return TRL_MAX_LEVELS;
83 }
84 
tpmi_get_trl_level_name(int level)85 static char *tpmi_get_trl_level_name(int level)
86 {
87 	switch (level) {
88 	case 0:
89 		return "level-0";
90 	case 1:
91 		return "level-1";
92 	case 2:
93 		return "level-2";
94 	case 3:
95 		return "level-3";
96 	case 4:
97 		return "level-4";
98 	case 5:
99 		return "level-5";
100 	case 6:
101 		return "level-6";
102 	case 7:
103 		return "level-7";
104 	default:
105 		return NULL;
106 	}
107 }
108 
109 
tpmi_update_platform_param(enum isst_platform_param param,int value)110 static void tpmi_update_platform_param(enum isst_platform_param param, int value)
111 {
112 	/* No params need to be updated for now */
113 }
114 
tpmi_is_punit_valid(struct isst_id * id)115 static int tpmi_is_punit_valid(struct isst_id *id)
116 {
117 	struct isst_tpmi_instance_count info;
118 	int ret;
119 
120 	if (id->punit < 0)
121 		return 0;
122 
123 	info.socket_id = id->pkg;
124 	ret = tpmi_process_ioctl(ISST_IF_COUNT_TPMI_INSTANCES, &info);
125 	if (ret == -1)
126 		return 0;
127 
128 	if (info.valid_mask & BIT(id->punit))
129 		return 1;
130 
131 	return 0;
132 }
133 
tpmi_read_pm_config(struct isst_id * id,int * cp_state,int * cp_cap)134 static int tpmi_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
135 {
136 	struct isst_core_power info;
137 	int ret;
138 
139 	info.get_set = 0;
140 	info.socket_id = id->pkg;
141 	info.power_domain_id = id->punit;
142 	ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
143 	if (ret == -1)
144 		return ret;
145 
146 	*cp_state = info.enable;
147 	*cp_cap = info.supported;
148 
149 	return 0;
150 }
151 
tpmi_get_config_levels(struct isst_id * id,struct isst_pkg_ctdp * pkg_dev)152 int tpmi_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
153 {
154 	struct isst_perf_level_info info;
155 	int ret;
156 
157 	info.socket_id = id->pkg;
158 	info.power_domain_id = id->punit;
159 
160 	ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
161 	if (ret == -1)
162 		return ret;
163 
164 	pkg_dev->version = info.feature_rev;
165 	pkg_dev->levels = info.max_level;
166 	pkg_dev->locked = info.locked;
167 	pkg_dev->current_level = info.current_level;
168 	pkg_dev->locked = info.locked;
169 	pkg_dev->enabled = info.enabled;
170 
171 	return 0;
172 }
173 
tpmi_get_ctdp_control(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)174 static int tpmi_get_ctdp_control(struct isst_id *id, int config_index,
175 				 struct isst_pkg_ctdp_level_info *ctdp_level)
176 {
177 	struct isst_core_power core_power_info;
178 	struct isst_perf_level_info info;
179 	int level_mask;
180 	int ret;
181 
182 	info.socket_id = id->pkg;
183 	info.power_domain_id = id->punit;
184 
185 	ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
186 	if (ret == -1)
187 		return -1;
188 
189 	if (config_index != 0xff)
190 		level_mask = 1 << config_index;
191 	else
192 		level_mask = config_index;
193 
194 	if (!(info.level_mask & level_mask))
195 		return -1;
196 
197 	if (api_version() > 2) {
198 		ctdp_level->fact_support = info.sst_tf_support & BIT(config_index);
199 		ctdp_level->pbf_support = info.sst_bf_support & BIT(config_index);
200 	} else {
201 		ctdp_level->fact_support = info.sst_tf_support;
202 		ctdp_level->pbf_support = info.sst_bf_support;
203 	}
204 
205 	ctdp_level->fact_enabled = !!(info.feature_state & BIT(1));
206 	ctdp_level->pbf_enabled = !!(info.feature_state & BIT(0));
207 
208 	core_power_info.get_set = 0;
209 	core_power_info.socket_id = id->pkg;
210 	core_power_info.power_domain_id = id->punit;
211 
212 	ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &core_power_info);
213 	if (ret == -1)
214 		return ret;
215 
216 	ctdp_level->sst_cp_support = core_power_info.supported;
217 	ctdp_level->sst_cp_enabled = core_power_info.enable;
218 
219 	debug_printf
220 	    ("cpu:%d CONFIG_TDP_GET_TDP_CONTROL fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
221 	     id->cpu, ctdp_level->fact_support, ctdp_level->pbf_support,
222 	     ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
223 
224 	return 0;
225 }
226 
tpmi_get_tdp_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)227 static int tpmi_get_tdp_info(struct isst_id *id, int config_index,
228 			     struct isst_pkg_ctdp_level_info *ctdp_level)
229 {
230 	struct isst_perf_level_fabric_info fabric_info;
231 	struct isst_perf_level_data_info info;
232 	int ret;
233 
234 	info.socket_id = id->pkg;
235 	info.power_domain_id = id->punit;
236 	info.level = config_index;
237 
238 	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
239 	if (ret == -1)
240 		return ret;
241 
242 	ctdp_level->pkg_tdp = info.thermal_design_power_w;
243 	ctdp_level->tdp_ratio = info.tdp_ratio;
244 	ctdp_level->sse_p1 = info.base_freq_mhz;
245 	ctdp_level->avx2_p1 = info.base_freq_avx2_mhz;
246 	ctdp_level->avx512_p1 = info.base_freq_avx512_mhz;
247 	ctdp_level->amx_p1 = info.base_freq_amx_mhz;
248 
249 	ctdp_level->t_proc_hot = info.tjunction_max_c;
250 	ctdp_level->mem_freq = info.max_memory_freq_mhz;
251 	ctdp_level->cooling_type = info.cooling_type;
252 
253 	ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
254 	ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
255 	ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
256 
257 	fabric_info.socket_id = id->pkg;
258 	fabric_info.power_domain_id = id->punit;
259 	fabric_info.level = config_index;
260 
261 	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_FABRIC_INFO, &fabric_info);
262 	if (ret != -1) {
263 		ctdp_level->uncore1_p0 = fabric_info.p0_fabric_freq_mhz[1];
264 		ctdp_level->uncore1_p1 = fabric_info.p1_fabric_freq_mhz[1];
265 		ctdp_level->uncore1_pm = fabric_info.pm_fabric_freq_mhz[1];
266 	}
267 
268 	debug_printf
269 	    ("cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO tdp_ratio:%d pkg_tdp:%d ctdp_level->t_proc_hot:%d\n",
270 	     id->cpu, config_index, ctdp_level->tdp_ratio, ctdp_level->pkg_tdp,
271 	     ctdp_level->t_proc_hot);
272 
273 	return 0;
274 }
275 
tpmi_get_pwr_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)276 static int tpmi_get_pwr_info(struct isst_id *id, int config_index,
277 			     struct isst_pkg_ctdp_level_info *ctdp_level)
278 {
279 	/* TBD */
280 	ctdp_level->pkg_max_power = 0;
281 	ctdp_level->pkg_min_power = 0;
282 
283 	debug_printf
284 	    ("cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO pkg_max_power:%d pkg_min_power:%d\n",
285 	     id->cpu, config_index, ctdp_level->pkg_max_power,
286 	     ctdp_level->pkg_min_power);
287 
288 	return 0;
289 }
290 
tpmi_get_coremask_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)291 int tpmi_get_coremask_info(struct isst_id *id, int config_index,
292 			   struct isst_pkg_ctdp_level_info *ctdp_level)
293 {
294 	struct isst_perf_level_cpu_mask info;
295 	int ret, cpu_count;
296 
297 	info.socket_id = id->pkg;
298 	info.power_domain_id = id->punit;
299 	info.level = config_index;
300 	info.punit_cpu_map = 1;
301 
302 	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_CPU_MASK, &info);
303 	if (ret == -1)
304 		return ret;
305 
306 	set_cpu_mask_from_punit_coremask(id, info.mask,
307 					 ctdp_level->core_cpumask_size,
308 					 ctdp_level->core_cpumask, &cpu_count);
309 	ctdp_level->cpu_count = cpu_count;
310 
311 	debug_printf("cpu:%d ctdp:%d core_mask ino cpu count:%d\n",
312 		     id->cpu, config_index, ctdp_level->cpu_count);
313 
314 	return 0;
315 }
316 
tpmi_get_get_trls(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)317 static int tpmi_get_get_trls(struct isst_id *id, int config_index,
318 			     struct isst_pkg_ctdp_level_info *ctdp_level)
319 {
320 	struct isst_perf_level_data_info info;
321 	int ret, i, j;
322 
323 	info.socket_id = id->pkg;
324 	info.power_domain_id = id->punit;
325 	info.level = config_index;
326 
327 	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
328 	if (ret == -1)
329 		return ret;
330 
331 	if (info.max_buckets > TRL_MAX_BUCKETS)
332 		info.max_buckets = TRL_MAX_BUCKETS;
333 
334 	if (info.max_trl_levels > TRL_MAX_LEVELS)
335 		info.max_trl_levels = TRL_MAX_LEVELS;
336 
337 	for (i = 0; i < info.max_trl_levels; ++i)
338 		for (j = 0; j < info.max_buckets; ++j)
339 			ctdp_level->trl_ratios[i][j] = info.trl_freq_mhz[i][j];
340 
341 	return 0;
342 }
343 
tpmi_get_get_trl(struct isst_id * id,int config_index,int level,int * trl)344 static int tpmi_get_get_trl(struct isst_id *id, int config_index, int level,
345 			    int *trl)
346 {
347 	struct isst_pkg_ctdp_level_info ctdp_level;
348 	int ret, i;
349 
350 	ret = tpmi_get_get_trls(id, config_index, &ctdp_level);
351 	if (ret)
352 		return ret;
353 
354 	/* FIX ME: Just return for level 0 */
355 	for (i = 0; i < 8; ++i)
356 		trl[i] = ctdp_level.trl_ratios[0][i];
357 
358 	return 0;
359 }
360 
tpmi_get_trl_bucket_info(struct isst_id * id,int config_index,unsigned long long * buckets_info)361 static int tpmi_get_trl_bucket_info(struct isst_id *id, int config_index,
362 				    unsigned long long *buckets_info)
363 {
364 	struct isst_perf_level_data_info info;
365 	unsigned char *mask = (unsigned char *)buckets_info;
366 	int ret, i;
367 
368 	info.socket_id = id->pkg;
369 	info.power_domain_id = id->punit;
370 	info.level = config_index;
371 
372 	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
373 	if (ret == -1)
374 		return ret;
375 
376 	if (info.max_buckets > TRL_MAX_BUCKETS)
377 		info.max_buckets = TRL_MAX_BUCKETS;
378 
379 	for (i = 0; i < info.max_buckets; ++i)
380 		mask[i] = info.bucket_core_counts[i];
381 
382 	debug_printf("cpu:%d TRL bucket info: 0x%llx\n", id->cpu,
383 		     *buckets_info);
384 
385 	return 0;
386 }
387 
tpmi_set_tdp_level(struct isst_id * id,int tdp_level)388 static int tpmi_set_tdp_level(struct isst_id *id, int tdp_level)
389 {
390 	struct isst_perf_level_control info;
391 	int ret;
392 
393 	info.socket_id = id->pkg;
394 	info.power_domain_id = id->punit;
395 	info.level = tdp_level;
396 
397 	ret = tpmi_process_ioctl(ISST_IF_PERF_SET_LEVEL, &info);
398 	if (ret == -1)
399 		return ret;
400 
401 	return 0;
402 }
403 
_pbf_get_coremask_info(struct isst_id * id,int config_index,struct isst_pbf_info * pbf_info)404 static int _pbf_get_coremask_info(struct isst_id *id, int config_index,
405 				  struct isst_pbf_info *pbf_info)
406 {
407 	struct isst_perf_level_cpu_mask info;
408 	int ret, cpu_count;
409 
410 	info.socket_id = id->pkg;
411 	info.power_domain_id = id->punit;
412 	info.level = config_index;
413 	info.punit_cpu_map = 1;
414 
415 	ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_CPU_MASK, &info);
416 	if (ret == -1)
417 		return ret;
418 
419 	set_cpu_mask_from_punit_coremask(id, info.mask,
420 					 pbf_info->core_cpumask_size,
421 					 pbf_info->core_cpumask, &cpu_count);
422 
423 	debug_printf("cpu:%d ctdp:%d pbf core_mask info cpu count:%d\n",
424 		     id->cpu, config_index, cpu_count);
425 
426 	return 0;
427 }
428 
tpmi_get_pbf_info(struct isst_id * id,int level,struct isst_pbf_info * pbf_info)429 static int tpmi_get_pbf_info(struct isst_id *id, int level,
430 			     struct isst_pbf_info *pbf_info)
431 {
432 	struct isst_base_freq_info info;
433 	int ret;
434 
435 	info.socket_id = id->pkg;
436 	info.power_domain_id = id->punit;
437 	info.level = level;
438 
439 	ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_INFO, &info);
440 	if (ret == -1)
441 		return ret;
442 
443 	pbf_info->p1_low = info.low_base_freq_mhz;
444 	pbf_info->p1_high = info.high_base_freq_mhz;
445 	pbf_info->tdp = info.thermal_design_power_w;
446 	pbf_info->t_prochot = info.tjunction_max_c;
447 
448 	debug_printf("cpu:%d ctdp:%d pbf info:%d:%d:%d:%d\n",
449 		     id->cpu, level, pbf_info->p1_low, pbf_info->p1_high,
450 		     pbf_info->tdp, pbf_info->t_prochot);
451 
452 	return _pbf_get_coremask_info(id, level, pbf_info);
453 }
454 
455 #define FEATURE_ENABLE_WAIT_US	1000
456 #define FEATURE_ENABLE_RETRIES	5
457 
tpmi_set_pbf_fact_status(struct isst_id * id,int pbf,int enable)458 static int tpmi_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
459 {
460 	struct isst_pkg_ctdp pkg_dev;
461 	struct isst_pkg_ctdp_level_info ctdp_level;
462 	int current_level;
463 	struct isst_perf_feature_control info;
464 	int ret, i;
465 
466 	ret = isst_get_ctdp_levels(id, &pkg_dev);
467 	if (ret)
468 		debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
469 
470 	current_level = pkg_dev.current_level;
471 
472 	ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
473 	if (ret)
474 		return ret;
475 
476 	info.socket_id = id->pkg;
477 	info.power_domain_id = id->punit;
478 
479 	info.feature = 0;
480 
481 	if (pbf) {
482 		if (ctdp_level.fact_enabled)
483 			info.feature |= BIT(1);
484 
485 		if (enable)
486 			info.feature |= BIT(0);
487 		else
488 			info.feature &= ~BIT(0);
489 	} else {
490 
491 		if (enable && !ctdp_level.sst_cp_enabled)
492 			isst_display_error_info_message(0,
493 							"Make sure to execute before: core-power enable",
494 							0, 0);
495 
496 		if (ctdp_level.pbf_enabled)
497 			info.feature |= BIT(0);
498 
499 		if (enable)
500 			info.feature |= BIT(1);
501 		else
502 			info.feature &= ~BIT(1);
503 	}
504 
505 	ret = tpmi_process_ioctl(ISST_IF_PERF_SET_FEATURE, &info);
506 	if (ret == -1)
507 		return ret;
508 
509 	for (i = 0; i < FEATURE_ENABLE_RETRIES; ++i) {
510 
511 		usleep(FEATURE_ENABLE_WAIT_US);
512 
513 		/* Check status */
514 		ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
515 		if (ret)
516 			return ret;
517 
518 		debug_printf("pbf_enabled:%d fact_enabled:%d\n",
519 			     ctdp_level.pbf_enabled, ctdp_level.fact_enabled);
520 
521 		if (pbf) {
522 			if (ctdp_level.pbf_enabled == enable)
523 				break;
524 		} else {
525 			if (ctdp_level.fact_enabled == enable)
526 				break;
527 		}
528 	}
529 
530 	if (i == FEATURE_ENABLE_RETRIES)
531 		return -1;
532 
533 	return 0;
534 }
535 
tpmi_get_fact_info(struct isst_id * id,int level,int fact_bucket,struct isst_fact_info * fact_info)536 static int tpmi_get_fact_info(struct isst_id *id, int level, int fact_bucket,
537 			      struct isst_fact_info *fact_info)
538 {
539 	struct isst_turbo_freq_info info;
540 	int i, j;
541 	int ret;
542 
543 	memset(&info, 0, sizeof(info));
544 	info.socket_id = id->pkg;
545 	info.power_domain_id = id->punit;
546 	info.level = level;
547 
548 	ret = tpmi_process_ioctl(ISST_IF_GET_TURBO_FREQ_INFO, &info);
549 	if (ret == -1)
550 		return ret;
551 
552 	for (i = 0; i < info.max_clip_freqs; ++i)
553 		fact_info->lp_ratios[i] = info.lp_clip_freq_mhz[i];
554 
555 	if (info.max_buckets > TRL_MAX_BUCKETS)
556 		info.max_buckets = TRL_MAX_BUCKETS;
557 
558 	if (info.max_trl_levels > TRL_MAX_LEVELS)
559 		info.max_trl_levels = TRL_MAX_LEVELS;
560 
561 	for (i = 0; i < info.max_trl_levels; ++i) {
562 		for (j = 0; j < info.max_buckets; ++j)
563 			fact_info->bucket_info[j].hp_ratios[i] =
564 			    info.trl_freq_mhz[i][j];
565 	}
566 
567 	for (i = 0; i < info.max_buckets; ++i)
568 		fact_info->bucket_info[i].hp_cores = info.bucket_core_counts[i];
569 
570 	return 0;
571 }
572 
_set_uncore_min_max(struct isst_id * id,int max,int freq)573 static void _set_uncore_min_max(struct isst_id *id, int max, int freq)
574 {
575 	DIR *dir;
576 	FILE *filep;
577 	struct dirent *entry;
578 	char buffer[512];
579 	unsigned int tmp_id;
580 	int ret;
581 
582 	dir = opendir("/sys/devices/system/cpu/intel_uncore_frequency/");
583 	if (!dir)
584 		return;
585 
586 	while ((entry = readdir(dir)) != NULL ) {
587 		/* Check domain_id */
588 		snprintf(buffer, sizeof(buffer),
589 			 "/sys/devices/system/cpu/intel_uncore_frequency/%s/domain_id", entry->d_name);
590 
591 		filep = fopen(buffer, "r");
592 		if (!filep)
593 			goto end;
594 
595 		ret = fscanf(filep, "%u", &tmp_id);
596 		fclose(filep);
597 		if (ret != 1)
598 			goto end;
599 
600 		if (tmp_id != id->punit)
601 			continue;
602 
603 		/* Check package_id */
604 		snprintf(buffer, sizeof(buffer),
605 			 "/sys/devices/system/cpu/intel_uncore_frequency/%s/package_id", entry->d_name);
606 
607 		filep = fopen(buffer, "r");
608 		if (!filep)
609 			goto end;
610 
611 		ret = fscanf(filep, "%u", &tmp_id);
612 		fclose(filep);
613 
614 		if (ret != 1)
615 			goto end;
616 
617 		if (tmp_id != id->pkg)
618 			continue;
619 
620 		/* Found the right sysfs path, adjust and quit */
621 		if (max)
622 			snprintf(buffer, sizeof(buffer),
623 				 "/sys/devices/system/cpu/intel_uncore_frequency/%s/max_freq_khz", entry->d_name);
624 		 else
625 			snprintf(buffer, sizeof(buffer),
626 				 "/sys/devices/system/cpu/intel_uncore_frequency/%s/min_freq_khz", entry->d_name);
627 
628 		filep = fopen(buffer, "w");
629 		if (!filep)
630 			goto end;
631 
632 		fprintf(filep, "%d\n", freq);
633 		fclose(filep);
634 		break;
635 	}
636 
637 end:
638 	closedir(dir);
639 }
640 
tpmi_adjust_uncore_freq(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)641 static void tpmi_adjust_uncore_freq(struct isst_id *id, int config_index,
642 				struct isst_pkg_ctdp_level_info *ctdp_level)
643 {
644 	struct isst_perf_level_data_info info;
645 	int ret;
646 
647 	info.socket_id = id->pkg;
648 	info.power_domain_id = id->punit;
649 	info.level = config_index;
650 
651 	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
652 	if (ret == -1)
653 		return;
654 
655 	ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
656 	ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
657 	ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
658 
659 	if (ctdp_level->uncore_pm)
660 		_set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000);
661 
662 	if (ctdp_level->uncore_p0)
663 		_set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000);
664 
665 	return;
666 }
667 
tpmi_get_clos_information(struct isst_id * id,int * enable,int * type)668 static int tpmi_get_clos_information(struct isst_id *id, int *enable, int *type)
669 {
670 	struct isst_core_power info;
671 	int ret;
672 
673 	info.get_set = 0;
674 	info.socket_id = id->pkg;
675 	info.power_domain_id = id->punit;
676 	ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
677 	if (ret == -1)
678 		return ret;
679 
680 	*enable = info.enable;
681 	*type = info.priority_type;
682 
683 	return 0;
684 }
685 
tpmi_pm_qos_config(struct isst_id * id,int enable_clos,int priority_type)686 static int tpmi_pm_qos_config(struct isst_id *id, int enable_clos,
687 			      int priority_type)
688 {
689 	struct isst_core_power info;
690 	int cp_state = 0, cp_cap = 0;
691 	int i, j, ret, saved_punit;
692 
693 	info.get_set = 1;
694 	info.socket_id = id->pkg;
695 	info.power_domain_id = id->punit;
696 	info.enable = enable_clos;
697 	info.priority_type = priority_type;
698 
699 	saved_punit = id->punit;
700 
701 	/* Set for all other dies also. This is per package setting */
702 	for (i = 0; i < MAX_PUNIT_PER_DIE; i++) {
703 		id->punit = i;
704 		if (isst_is_punit_valid(id)) {
705 			info.power_domain_id = i;
706 			ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
707 			if (ret == -1) {
708 				id->punit = saved_punit;
709 				return ret;
710 			}
711 			/* Get status */
712 			for (j = 0; j < FEATURE_ENABLE_RETRIES; ++j) {
713 				usleep(FEATURE_ENABLE_WAIT_US);
714 				ret = tpmi_read_pm_config(id, &cp_state, &cp_cap);
715 				debug_printf("ret:%d cp_state:%d enable_clos:%d\n", ret,
716 					     cp_state, enable_clos);
717 				if (ret || cp_state == enable_clos)
718 					break;
719 			}
720 			if (j == FEATURE_ENABLE_RETRIES) {
721 				id->punit = saved_punit;
722 				return -1;
723 			}
724 		}
725 	}
726 
727 	id->punit = saved_punit;
728 
729 	return 0;
730 }
731 
tpmi_pm_get_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)732 int tpmi_pm_get_clos(struct isst_id *id, int clos,
733 		     struct isst_clos_config *clos_config)
734 {
735 	struct isst_clos_param info;
736 	int ret;
737 
738 	info.get_set = 0;
739 	info.socket_id = id->pkg;
740 	info.power_domain_id = id->punit;
741 	info.clos = clos;
742 
743 	ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
744 	if (ret == -1)
745 		return ret;
746 
747 	clos_config->epp = 0;
748 	clos_config->clos_prop_prio = info.prop_prio;
749 	clos_config->clos_min = info.min_freq_mhz;
750 	clos_config->clos_max = info.max_freq_mhz;
751 	clos_config->clos_desired = 0;
752 
753 	debug_printf("cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
754 		     clos_config->clos_min, clos_config->clos_max);
755 
756 	return 0;
757 }
758 
tpmi_set_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)759 int tpmi_set_clos(struct isst_id *id, int clos,
760 		  struct isst_clos_config *clos_config)
761 {
762 	struct isst_clos_param info;
763 	int i, ret, saved_punit;
764 
765 	info.get_set = 1;
766 	info.socket_id = id->pkg;
767 	info.power_domain_id = id->punit;
768 	info.clos = clos;
769 	info.prop_prio = clos_config->clos_prop_prio;
770 
771 	info.min_freq_mhz = clos_config->clos_min;
772 	info.max_freq_mhz = clos_config->clos_max;
773 
774 	if (info.min_freq_mhz <= 0xff)
775 		info.min_freq_mhz *= 100;
776 	if (info.max_freq_mhz <= 0xff)
777 		info.max_freq_mhz *= 100;
778 
779 	saved_punit = id->punit;
780 
781 	/* Set for all other dies also. This is per package setting */
782 	for (i = 0; i < MAX_PUNIT_PER_DIE; i++) {
783 		id->punit = i;
784 		if (isst_is_punit_valid(id)) {
785 			info.power_domain_id = i;
786 			ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
787 			if (ret == -1) {
788 				id->punit = saved_punit;
789 				return ret;
790 			}
791 		}
792 	}
793 
794 	id->punit = saved_punit;
795 
796 	debug_printf("set cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
797 		     clos_config->clos_min, clos_config->clos_max);
798 
799 	return 0;
800 }
801 
tpmi_clos_get_assoc_status(struct isst_id * id,int * clos_id)802 static int tpmi_clos_get_assoc_status(struct isst_id *id, int *clos_id)
803 {
804 	struct isst_if_clos_assoc_cmds assoc_cmds;
805 	int ret;
806 
807 	assoc_cmds.cmd_count = 1;
808 	assoc_cmds.get_set = 0;
809 	assoc_cmds.punit_cpu_map = 1;
810 	assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
811 	assoc_cmds.assoc_info[0].socket_id = id->pkg;
812 	assoc_cmds.assoc_info[0].power_domain_id = id->punit;
813 
814 	ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
815 	if (ret == -1)
816 		return ret;
817 
818 	*clos_id = assoc_cmds.assoc_info[0].clos;
819 
820 	return 0;
821 }
822 
tpmi_clos_associate(struct isst_id * id,int clos_id)823 static int tpmi_clos_associate(struct isst_id *id, int clos_id)
824 {
825 	struct isst_if_clos_assoc_cmds assoc_cmds;
826 	int ret;
827 
828 	assoc_cmds.cmd_count = 1;
829 	assoc_cmds.get_set = 1;
830 	assoc_cmds.punit_cpu_map = 1;
831 	assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
832 	assoc_cmds.assoc_info[0].clos = clos_id;
833 	assoc_cmds.assoc_info[0].socket_id = id->pkg;
834 	assoc_cmds.assoc_info[0].power_domain_id = id->punit;
835 
836 	ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
837 	if (ret == -1)
838 		return ret;
839 
840 	return 0;
841 }
842 
843 static struct isst_platform_ops tpmi_ops = {
844 	.get_disp_freq_multiplier = tpmi_get_disp_freq_multiplier,
845 	.get_trl_max_levels = tpmi_get_trl_max_levels,
846 	.get_trl_level_name = tpmi_get_trl_level_name,
847 	.update_platform_param = tpmi_update_platform_param,
848 	.is_punit_valid = tpmi_is_punit_valid,
849 	.read_pm_config = tpmi_read_pm_config,
850 	.get_config_levels = tpmi_get_config_levels,
851 	.get_ctdp_control = tpmi_get_ctdp_control,
852 	.get_tdp_info = tpmi_get_tdp_info,
853 	.get_pwr_info = tpmi_get_pwr_info,
854 	.get_coremask_info = tpmi_get_coremask_info,
855 	.get_get_trl = tpmi_get_get_trl,
856 	.get_get_trls = tpmi_get_get_trls,
857 	.get_trl_bucket_info = tpmi_get_trl_bucket_info,
858 	.set_tdp_level = tpmi_set_tdp_level,
859 	.get_pbf_info = tpmi_get_pbf_info,
860 	.set_pbf_fact_status = tpmi_set_pbf_fact_status,
861 	.get_fact_info = tpmi_get_fact_info,
862 	.adjust_uncore_freq = tpmi_adjust_uncore_freq,
863 	.get_clos_information = tpmi_get_clos_information,
864 	.pm_qos_config = tpmi_pm_qos_config,
865 	.pm_get_clos = tpmi_pm_get_clos,
866 	.set_clos = tpmi_set_clos,
867 	.clos_get_assoc_status = tpmi_clos_get_assoc_status,
868 	.clos_associate = tpmi_clos_associate,
869 };
870 
tpmi_get_platform_ops(void)871 struct isst_platform_ops *tpmi_get_platform_ops(void)
872 {
873 	return &tpmi_ops;
874 }
875