1 // SPDX-License-Identifier: GPL-2.0
3 * Intel dynamic_speed_select -- Enumerate and control features
4 * Copyright (c) 2019 Intel Corporation.
9 static void printcpulist(int str_len, char *str, int mask_size,
12 int i, first, curr_index, index;
14 if (!CPU_COUNT_S(mask_size, cpu_mask)) {
15 snprintf(str, str_len, "none");
21 for (i = 0; i < get_topo_max_cpus(); ++i) {
22 if (!CPU_ISSET_S(i, mask_size, cpu_mask))
25 index = snprintf(&str[curr_index],
26 str_len - curr_index, ",");
28 if (curr_index >= str_len)
31 index = snprintf(&str[curr_index], str_len - curr_index, "%d",
34 if (curr_index >= str_len)
40 static void printcpumask(int str_len, char *str, int mask_size,
43 int i, max_cpus = get_topo_max_cpus();
45 int size, index, curr_index;
47 size = max_cpus / (sizeof(unsigned int) * 8);
48 if (max_cpus % (sizeof(unsigned int) * 8))
51 mask = calloc(size, sizeof(unsigned int));
55 for (i = 0; i < max_cpus; ++i) {
56 int mask_index, bit_index;
58 if (!CPU_ISSET_S(i, mask_size, cpu_mask))
61 mask_index = i / (sizeof(unsigned int) * 8);
62 bit_index = i % (sizeof(unsigned int) * 8);
63 mask[mask_index] |= BIT(bit_index);
67 for (i = size - 1; i >= 0; --i) {
68 index = snprintf(&str[curr_index], str_len - curr_index, "%08x",
71 if (curr_index >= str_len)
74 strncat(&str[curr_index], ",", str_len - curr_index);
77 if (curr_index >= str_len)
84 static void format_and_print_txt(FILE *outf, int level, char *header,
88 static char delimiters[256];
95 strcpy(delimiters, " ");
97 for (i = 0; i < level - 1; ++i)
98 j += snprintf(&delimiters[j], sizeof(delimiters) - j,
102 if (header && value) {
103 fprintf(outf, "%s", delimiters);
104 fprintf(outf, "%s:%s\n", header, value);
106 fprintf(outf, "%s", delimiters);
107 fprintf(outf, "%s\n", header);
111 static int last_level;
112 static void format_and_print(FILE *outf, int level, char *header, char *value)
115 static char delimiters[256];
118 if (!out_format_is_json()) {
119 format_and_print_txt(outf, level, header, value);
127 fprintf(outf, "\n}\n");
132 for (i = 0; i < level; ++i)
133 j += snprintf(&delimiters[j], sizeof(delimiters) - j,
136 if (last_level == level)
137 fprintf(outf, ",\n");
140 if (last_level != level)
143 fprintf(outf, "%s\"%s\": ", delimiters, header);
144 fprintf(outf, "\"%s\"", value);
146 for (i = last_level - 1; i >= level; --i) {
149 for (j = i; j > 0; --j)
150 k += snprintf(&delimiters[k],
151 sizeof(delimiters) - k,
153 if (i == level && header)
154 fprintf(outf, "\n%s},", delimiters);
156 fprintf(outf, "\n%s}", delimiters);
158 if (abs(last_level - level) < 3)
161 fprintf(outf, "%s\"%s\": {", delimiters,
169 static int print_package_info(struct isst_id *id, FILE *outf)
174 if (out_format_is_json()) {
175 if (api_version() > 1)
176 snprintf(header, sizeof(header), "package-%d:die-%d:powerdomain-%d:cpu-%d",
177 id->pkg, id->die, id->punit, id->cpu);
179 snprintf(header, sizeof(header), "package-%d:die-%d:cpu-%d",
180 id->pkg, id->die, id->cpu);
181 format_and_print(outf, level, header, NULL);
184 snprintf(header, sizeof(header), "package-%d", id->pkg);
185 format_and_print(outf, level++, header, NULL);
186 snprintf(header, sizeof(header), "die-%d", id->die);
187 format_and_print(outf, level++, header, NULL);
188 if (api_version() > 1) {
189 snprintf(header, sizeof(header), "powerdomain-%d", id->punit);
190 format_and_print(outf, level++, header, NULL);
192 snprintf(header, sizeof(header), "cpu-%d", id->cpu);
193 format_and_print(outf, level, header, NULL);
198 static void _isst_pbf_display_information(struct isst_id *id, FILE *outf, int level,
199 struct isst_pbf_info *pbf_info,
205 snprintf(header, sizeof(header), "speed-select-base-freq-properties");
206 format_and_print(outf, disp_level, header, NULL);
208 snprintf(header, sizeof(header), "high-priority-base-frequency(MHz)");
209 snprintf(value, sizeof(value), "%d",
210 pbf_info->p1_high * isst_get_disp_freq_multiplier());
211 format_and_print(outf, disp_level + 1, header, value);
213 snprintf(header, sizeof(header), "high-priority-cpu-mask");
214 printcpumask(sizeof(value), value, pbf_info->core_cpumask_size,
215 pbf_info->core_cpumask);
216 format_and_print(outf, disp_level + 1, header, value);
218 snprintf(header, sizeof(header), "high-priority-cpu-list");
219 printcpulist(sizeof(value), value,
220 pbf_info->core_cpumask_size,
221 pbf_info->core_cpumask);
222 format_and_print(outf, disp_level + 1, header, value);
224 snprintf(header, sizeof(header), "low-priority-base-frequency(MHz)");
225 snprintf(value, sizeof(value), "%d",
226 pbf_info->p1_low * isst_get_disp_freq_multiplier());
227 format_and_print(outf, disp_level + 1, header, value);
229 if (is_clx_n_platform())
232 snprintf(header, sizeof(header), "tjunction-temperature(C)");
233 snprintf(value, sizeof(value), "%d", pbf_info->t_prochot);
234 format_and_print(outf, disp_level + 1, header, value);
236 snprintf(header, sizeof(header), "thermal-design-power(W)");
237 snprintf(value, sizeof(value), "%d", pbf_info->tdp);
238 format_and_print(outf, disp_level + 1, header, value);
241 static void _isst_fact_display_information(struct isst_id *id, FILE *outf, int level,
242 int fact_bucket, int fact_avx,
243 struct isst_fact_info *fact_info,
246 struct isst_fact_bucket_info *bucket_info = fact_info->bucket_info;
247 int trl_max_levels = isst_get_trl_max_levels();
252 for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
253 if (fact_bucket != 0xff && fact_bucket != j)
256 /* core count must be valid for CPU power domain */
257 if (!bucket_info[j].hp_cores && id->cpu >= 0)
263 fprintf(stderr, "Invalid bucket\n");
267 snprintf(header, sizeof(header), "speed-select-turbo-freq-properties");
268 format_and_print(outf, base_level, header, NULL);
269 for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
272 if (fact_bucket != 0xff && fact_bucket != j)
275 if (!bucket_info[j].hp_cores)
278 snprintf(header, sizeof(header), "bucket-%d", j);
279 format_and_print(outf, base_level + 1, header, NULL);
281 snprintf(header, sizeof(header), "high-priority-cores-count");
282 snprintf(value, sizeof(value), "%d",
283 bucket_info[j].hp_cores);
284 format_and_print(outf, base_level + 2, header, value);
285 for (i = 0; i < trl_max_levels; i++) {
286 if (!bucket_info[j].hp_ratios[i] || (fact_avx != 0xFF && !(fact_avx & (1 << i))))
288 if (i == 0 && api_version() == 1 && !is_emr_platform())
289 snprintf(header, sizeof(header),
290 "high-priority-max-frequency(MHz)");
292 snprintf(header, sizeof(header),
293 "high-priority-max-%s-frequency(MHz)", isst_get_trl_level_name(i));
294 snprintf(value, sizeof(value), "%d",
295 bucket_info[j].hp_ratios[i] * isst_get_disp_freq_multiplier());
296 format_and_print(outf, base_level + 2, header, value);
299 snprintf(header, sizeof(header),
300 "speed-select-turbo-freq-clip-frequencies");
301 format_and_print(outf, base_level + 1, header, NULL);
303 for (j = 0; j < trl_max_levels; j++) {
304 if (!fact_info->lp_ratios[j])
307 /* No AVX level name for SSE to be consistent with previous formatting */
308 if (j == 0 && api_version() == 1 && !is_emr_platform())
309 snprintf(header, sizeof(header), "low-priority-max-frequency(MHz)");
311 snprintf(header, sizeof(header), "low-priority-max-%s-frequency(MHz)",
312 isst_get_trl_level_name(j));
313 snprintf(value, sizeof(value), "%d",
314 fact_info->lp_ratios[j] * isst_get_disp_freq_multiplier());
315 format_and_print(outf, base_level + 2, header, value);
319 void isst_ctdp_display_core_info(struct isst_id *id, FILE *outf, char *prefix,
320 unsigned int val, char *str0, char *str1)
323 int level = print_package_info(id, outf);
328 snprintf(value, sizeof(value), "%s", str0);
329 else if (str1 && val)
330 snprintf(value, sizeof(value), "%s", str1);
332 snprintf(value, sizeof(value), "%u", val);
333 format_and_print(outf, level, prefix, value);
335 format_and_print(outf, 1, NULL, NULL);
338 void isst_ctdp_display_information(struct isst_id *id, FILE *outf, int tdp_level,
339 struct isst_pkg_ctdp *pkg_dev)
344 int trl_max_levels = isst_get_trl_max_levels();
347 if (pkg_dev->processed)
348 level = print_package_info(id, outf);
350 for (i = 0; i <= pkg_dev->levels; ++i) {
351 struct isst_pkg_ctdp_level_info *ctdp_level;
354 ctdp_level = &pkg_dev->ctdp_level[i];
355 if (!ctdp_level->processed)
358 snprintf(header, sizeof(header), "perf-profile-level-%d",
360 format_and_print(outf, level + 1, header, NULL);
363 snprintf(header, sizeof(header), "cpu-count");
364 j = get_cpu_count(id);
365 snprintf(value, sizeof(value), "%d", j);
366 format_and_print(outf, level + 2, header, value);
368 j = CPU_COUNT_S(ctdp_level->core_cpumask_size,
369 ctdp_level->core_cpumask);
371 snprintf(header, sizeof(header), "enable-cpu-count");
372 snprintf(value, sizeof(value), "%d", j);
373 format_and_print(outf, level + 2, header, value);
376 if (ctdp_level->core_cpumask_size) {
377 snprintf(header, sizeof(header), "enable-cpu-mask");
378 printcpumask(sizeof(value), value,
379 ctdp_level->core_cpumask_size,
380 ctdp_level->core_cpumask);
381 format_and_print(outf, level + 2, header, value);
383 snprintf(header, sizeof(header), "enable-cpu-list");
384 printcpulist(sizeof(value), value,
385 ctdp_level->core_cpumask_size,
386 ctdp_level->core_cpumask);
387 format_and_print(outf, level + 2, header, value);
391 snprintf(header, sizeof(header), "thermal-design-power-ratio");
392 snprintf(value, sizeof(value), "%d", ctdp_level->tdp_ratio);
393 format_and_print(outf, level + 2, header, value);
395 snprintf(header, sizeof(header), "base-frequency(MHz)");
396 if (!ctdp_level->sse_p1)
397 ctdp_level->sse_p1 = ctdp_level->tdp_ratio;
398 snprintf(value, sizeof(value), "%d",
399 ctdp_level->sse_p1 * isst_get_disp_freq_multiplier());
400 format_and_print(outf, level + 2, header, value);
402 if (ctdp_level->avx2_p1) {
403 snprintf(header, sizeof(header), "base-frequency-avx2(MHz)");
404 snprintf(value, sizeof(value), "%d",
405 ctdp_level->avx2_p1 * isst_get_disp_freq_multiplier());
406 format_and_print(outf, level + 2, header, value);
409 if (ctdp_level->avx512_p1) {
410 snprintf(header, sizeof(header), "base-frequency-avx512(MHz)");
411 snprintf(value, sizeof(value), "%d",
412 ctdp_level->avx512_p1 * isst_get_disp_freq_multiplier());
413 format_and_print(outf, level + 2, header, value);
416 if (ctdp_level->uncore_pm) {
417 snprintf(header, sizeof(header), "uncore-frequency-min(MHz)");
418 snprintf(value, sizeof(value), "%d",
419 ctdp_level->uncore_pm * isst_get_disp_freq_multiplier());
420 format_and_print(outf, level + 2, header, value);
423 if (ctdp_level->uncore_p0) {
424 snprintf(header, sizeof(header), "uncore-frequency-max(MHz)");
425 snprintf(value, sizeof(value), "%d",
426 ctdp_level->uncore_p0 * isst_get_disp_freq_multiplier());
427 format_and_print(outf, level + 2, header, value);
430 if (ctdp_level->amx_p1) {
431 snprintf(header, sizeof(header), "base-frequency-amx(MHz)");
432 snprintf(value, sizeof(value), "%d",
433 ctdp_level->amx_p1 * isst_get_disp_freq_multiplier());
434 format_and_print(outf, level + 2, header, value);
437 if (ctdp_level->uncore_p1) {
438 snprintf(header, sizeof(header), "uncore-frequency-base(MHz)");
439 snprintf(value, sizeof(value), "%d",
440 ctdp_level->uncore_p1 * isst_get_disp_freq_multiplier());
441 format_and_print(outf, level + 2, header, value);
444 if (ctdp_level->mem_freq) {
445 snprintf(header, sizeof(header), "max-mem-frequency(MHz)");
446 snprintf(value, sizeof(value), "%d",
447 ctdp_level->mem_freq);
448 format_and_print(outf, level + 2, header, value);
451 if (api_version() > 1) {
452 snprintf(header, sizeof(header), "cooling_type");
453 snprintf(value, sizeof(value), "%d",
454 ctdp_level->cooling_type);
455 format_and_print(outf, level + 2, header, value);
458 snprintf(header, sizeof(header),
459 "speed-select-turbo-freq");
460 if (ctdp_level->fact_support) {
461 if (ctdp_level->fact_enabled)
462 snprintf(value, sizeof(value), "enabled");
464 snprintf(value, sizeof(value), "disabled");
466 snprintf(value, sizeof(value), "unsupported");
467 format_and_print(outf, level + 2, header, value);
469 snprintf(header, sizeof(header),
470 "speed-select-base-freq");
471 if (ctdp_level->pbf_support) {
472 if (ctdp_level->pbf_enabled)
473 snprintf(value, sizeof(value), "enabled");
475 snprintf(value, sizeof(value), "disabled");
477 snprintf(value, sizeof(value), "unsupported");
478 format_and_print(outf, level + 2, header, value);
480 snprintf(header, sizeof(header),
481 "speed-select-core-power");
482 if (ctdp_level->sst_cp_support) {
483 if (ctdp_level->sst_cp_enabled)
484 snprintf(value, sizeof(value), "enabled");
486 snprintf(value, sizeof(value), "disabled");
488 snprintf(value, sizeof(value), "unsupported");
489 format_and_print(outf, level + 2, header, value);
491 if (is_clx_n_platform()) {
492 if (ctdp_level->pbf_support)
493 _isst_pbf_display_information(id, outf,
495 &ctdp_level->pbf_info,
500 if (ctdp_level->pkg_tdp) {
501 snprintf(header, sizeof(header), "thermal-design-power(W)");
502 snprintf(value, sizeof(value), "%d", ctdp_level->pkg_tdp);
503 format_and_print(outf, level + 2, header, value);
506 if (ctdp_level->t_proc_hot) {
507 snprintf(header, sizeof(header), "tjunction-max(C)");
508 snprintf(value, sizeof(value), "%d", ctdp_level->t_proc_hot);
509 format_and_print(outf, level + 2, header, value);
512 for (k = 0; k < trl_max_levels; k++) {
513 if (!ctdp_level->trl_ratios[k][0])
516 snprintf(header, sizeof(header), "turbo-ratio-limits-%s", isst_get_trl_level_name(k));
517 format_and_print(outf, level + 2, header, NULL);
519 for (j = 0; j < 8; ++j) {
520 snprintf(header, sizeof(header), "bucket-%d", j);
521 format_and_print(outf, level + 3, header, NULL);
523 snprintf(header, sizeof(header), "core-count");
525 snprintf(value, sizeof(value), "%llu", (ctdp_level->trl_cores >> (j * 8)) & 0xff);
526 format_and_print(outf, level + 4, header, value);
528 snprintf(header, sizeof(header), "max-turbo-frequency(MHz)");
529 snprintf(value, sizeof(value), "%d", ctdp_level->trl_ratios[k][j] * isst_get_disp_freq_multiplier());
530 format_and_print(outf, level + 4, header, value);
534 if (ctdp_level->pbf_support)
535 _isst_pbf_display_information(id, outf, i,
536 &ctdp_level->pbf_info,
538 if (ctdp_level->fact_support)
539 _isst_fact_display_information(id, outf, i, 0xff, 0xff,
540 &ctdp_level->fact_info,
544 format_and_print(outf, 1, NULL, NULL);
548 void isst_ctdp_display_information_start(FILE *outf)
551 format_and_print(outf, 0, "start", NULL);
555 void isst_ctdp_display_information_end(FILE *outf)
557 format_and_print(outf, 0, NULL, NULL);
561 void isst_pbf_display_information(struct isst_id *id, FILE *outf, int level,
562 struct isst_pbf_info *pbf_info)
566 _level = print_package_info(id, outf);
567 _isst_pbf_display_information(id, outf, level, pbf_info, _level + 1);
568 format_and_print(outf, 1, NULL, NULL);
571 void isst_fact_display_information(struct isst_id *id, FILE *outf, int level,
572 int fact_bucket, int fact_avx,
573 struct isst_fact_info *fact_info)
577 _level = print_package_info(id, outf);
578 _isst_fact_display_information(id, outf, level, fact_bucket, fact_avx,
579 fact_info, _level + 1);
580 format_and_print(outf, 1, NULL, NULL);
583 void isst_clos_display_information(struct isst_id *id, FILE *outf, int clos,
584 struct isst_clos_config *clos_config)
590 level = print_package_info(id, outf);
592 snprintf(header, sizeof(header), "core-power");
593 format_and_print(outf, level + 1, header, NULL);
595 snprintf(header, sizeof(header), "clos");
596 snprintf(value, sizeof(value), "%d", clos);
597 format_and_print(outf, level + 2, header, value);
599 snprintf(header, sizeof(header), "epp");
600 snprintf(value, sizeof(value), "%d", clos_config->epp);
601 format_and_print(outf, level + 2, header, value);
603 snprintf(header, sizeof(header), "clos-proportional-priority");
604 snprintf(value, sizeof(value), "%d", clos_config->clos_prop_prio);
605 format_and_print(outf, level + 2, header, value);
607 snprintf(header, sizeof(header), "clos-min");
608 snprintf(value, sizeof(value), "%d MHz", clos_config->clos_min * isst_get_disp_freq_multiplier());
609 format_and_print(outf, level + 2, header, value);
611 snprintf(header, sizeof(header), "clos-max");
612 if ((clos_config->clos_max * isst_get_disp_freq_multiplier()) == 25500)
613 snprintf(value, sizeof(value), "Max Turbo frequency");
615 snprintf(value, sizeof(value), "%d MHz", clos_config->clos_max * isst_get_disp_freq_multiplier());
616 format_and_print(outf, level + 2, header, value);
618 snprintf(header, sizeof(header), "clos-desired");
619 snprintf(value, sizeof(value), "%d MHz", clos_config->clos_desired * isst_get_disp_freq_multiplier());
620 format_and_print(outf, level + 2, header, value);
622 format_and_print(outf, level, NULL, NULL);
625 void isst_clos_display_clos_information(struct isst_id *id, FILE *outf,
626 int clos_enable, int type,
633 level = print_package_info(id, outf);
635 snprintf(header, sizeof(header), "core-power");
636 format_and_print(outf, level + 1, header, NULL);
638 snprintf(header, sizeof(header), "support-status");
640 snprintf(value, sizeof(value), "supported");
642 snprintf(value, sizeof(value), "unsupported");
643 format_and_print(outf, level + 2, header, value);
645 snprintf(header, sizeof(header), "enable-status");
647 snprintf(value, sizeof(value), "enabled");
649 snprintf(value, sizeof(value), "disabled");
650 format_and_print(outf, level + 2, header, value);
652 snprintf(header, sizeof(header), "clos-enable-status");
654 snprintf(value, sizeof(value), "enabled");
656 snprintf(value, sizeof(value), "disabled");
657 format_and_print(outf, level + 2, header, value);
659 snprintf(header, sizeof(header), "priority-type");
661 snprintf(value, sizeof(value), "ordered");
663 snprintf(value, sizeof(value), "proportional");
664 format_and_print(outf, level + 2, header, value);
666 format_and_print(outf, level, NULL, NULL);
669 void isst_clos_display_assoc_information(struct isst_id *id, FILE *outf, int clos)
675 level = print_package_info(id, outf);
677 snprintf(header, sizeof(header), "get-assoc");
678 format_and_print(outf, level + 1, header, NULL);
680 snprintf(header, sizeof(header), "clos");
681 snprintf(value, sizeof(value), "%d", clos);
682 format_and_print(outf, level + 2, header, value);
684 format_and_print(outf, level, NULL, NULL);
687 void isst_display_result(struct isst_id *id, FILE *outf, char *feature, char *cmd,
694 level = print_package_info(id, outf);
696 snprintf(header, sizeof(header), "%s", feature);
697 format_and_print(outf, level + 1, header, NULL);
698 snprintf(header, sizeof(header), "%s", cmd);
700 snprintf(value, sizeof(value), "success");
702 snprintf(value, sizeof(value), "failed(error %d)", result);
703 format_and_print(outf, level + 2, header, value);
705 format_and_print(outf, level, NULL, NULL);
708 void isst_display_error_info_message(int error, char *msg, int arg_valid, int arg)
710 FILE *outf = get_output_file();
711 static int error_index;
715 if (!out_format_is_json()) {
717 snprintf(value, sizeof(value), "%s %d", msg, arg);
719 snprintf(value, sizeof(value), "%s", msg);
722 fprintf(outf, "Error: %s\n", value);
724 fprintf(outf, "Information: %s\n", value);
729 format_and_print(outf, 0, "start", NULL);
732 snprintf(header, sizeof(header), "Error%d", error_index++);
734 snprintf(header, sizeof(header), "Information:%d", error_index++);
735 format_and_print(outf, 1, header, NULL);
737 snprintf(header, sizeof(header), "message");
739 snprintf(value, sizeof(value), "%s %d", msg, arg);
741 snprintf(value, sizeof(value), "%s", msg);
743 format_and_print(outf, 2, header, value);
744 format_and_print(outf, 1, NULL, NULL);
746 format_and_print(outf, 0, NULL, NULL);
749 void isst_trl_display_information(struct isst_id *id, FILE *outf, unsigned long long trl)
755 level = print_package_info(id, outf);
757 snprintf(header, sizeof(header), "get-trl");
758 format_and_print(outf, level + 1, header, NULL);
760 snprintf(header, sizeof(header), "trl");
761 snprintf(value, sizeof(value), "0x%llx", trl);
762 format_and_print(outf, level + 2, header, value);
764 format_and_print(outf, level, NULL, NULL);