Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/power/x86/intel-speed-select/isst-core-tpmi.c
53512 views
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
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
75
static int tpmi_get_disp_freq_multiplier(void)
76
{
77
return 1;
78
}
79
80
static int tpmi_get_trl_max_levels(void)
81
{
82
return TRL_MAX_LEVELS;
83
}
84
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
871
struct isst_platform_ops *tpmi_get_platform_ops(void)
872
{
873
return &tpmi_ops;
874
}
875
876