File Index
Files and directories
Sign in
FILE

isst-core-tpmi.c

File preview with syntax highlighting.

linux-6.19.14/tools/power/x86/intel-speed-select/isst-core-tpmi.c C
  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
 10int 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
 75static int tpmi_get_disp_freq_multiplier(void)
 76{
 77	return 1;
 78}
 79
 80static int tpmi_get_trl_max_levels(void)
 81{
 82	return TRL_MAX_LEVELS;
 83}
 84
 85static 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
110static void tpmi_update_platform_param(enum isst_platform_param param, int value)
111{
112	/* No params need to be updated for now */
113}
114
115static 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
134static 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
152int 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
174static 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
227static 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
276static 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
291int 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
317static 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
344static 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
361static 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
388static 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
404static 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
429static 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
458static 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
536static 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
573static 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
637end:
638	closedir(dir);
639}
640
641static 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
668static 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
686static 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
732int 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
759int 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
802static 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
823static 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
843static 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
871struct isst_platform_ops *tpmi_get_platform_ops(void)
872{
873	return &tpmi_ops;
874}
~/ Read-only file preview.