1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Intel Speed Select -- Enumerate and control features
4  * Copyright (c) 2019 Intel Corporation.
5  */
6 
7 #include "isst.h"
8 
isst_write_pm_config(struct isst_id * id,int cp_state)9 int isst_write_pm_config(struct isst_id *id, int cp_state)
10 {
11 	unsigned int req, resp;
12 	int ret;
13 
14 	if (cp_state)
15 		req = BIT(16);
16 	else
17 		req = 0;
18 
19 	ret = isst_send_mbox_command(id->cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
20 				     &resp);
21 	if (ret)
22 		return ret;
23 
24 	debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp);
25 
26 	return 0;
27 }
28 
isst_read_pm_config(struct isst_id * id,int * cp_state,int * cp_cap)29 int isst_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
30 {
31 	unsigned int resp;
32 	int ret;
33 
34 	ret = isst_send_mbox_command(id->cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
35 				     &resp);
36 	if (ret)
37 		return ret;
38 
39 	debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", id->cpu, resp);
40 
41 	*cp_state = resp & BIT(16);
42 	*cp_cap = resp & BIT(0) ? 1 : 0;
43 
44 	return 0;
45 }
46 
isst_get_ctdp_levels(struct isst_id * id,struct isst_pkg_ctdp * pkg_dev)47 int isst_get_ctdp_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
48 {
49 	unsigned int resp;
50 	int ret;
51 
52 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
53 				     CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
54 	if (ret) {
55 		pkg_dev->levels = 0;
56 		pkg_dev->locked = 1;
57 		pkg_dev->current_level = 0;
58 		pkg_dev->version = 0;
59 		pkg_dev->enabled = 0;
60 		return 0;
61 	}
62 
63 	debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", id->cpu, resp);
64 
65 	pkg_dev->version = resp & 0xff;
66 	pkg_dev->levels = (resp >> 8) & 0xff;
67 	pkg_dev->current_level = (resp >> 16) & 0xff;
68 	pkg_dev->locked = !!(resp & BIT(24));
69 	pkg_dev->enabled = !!(resp & BIT(31));
70 
71 	return 0;
72 }
73 
isst_get_ctdp_control(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)74 int isst_get_ctdp_control(struct isst_id *id, int config_index,
75 			  struct isst_pkg_ctdp_level_info *ctdp_level)
76 {
77 	int cp_state, cp_cap;
78 	unsigned int resp;
79 	int ret;
80 
81 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
82 				     CONFIG_TDP_GET_TDP_CONTROL, 0,
83 				     config_index, &resp);
84 	if (ret)
85 		return ret;
86 
87 	ctdp_level->fact_support = resp & BIT(0);
88 	ctdp_level->pbf_support = !!(resp & BIT(1));
89 	ctdp_level->fact_enabled = !!(resp & BIT(16));
90 	ctdp_level->pbf_enabled = !!(resp & BIT(17));
91 
92 	ret = isst_read_pm_config(id, &cp_state, &cp_cap);
93 	if (ret) {
94 		debug_printf("cpu:%d pm_config is not supported\n", id->cpu);
95 	} else {
96 		debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d\n", id->cpu, cp_state, cp_cap);
97 		ctdp_level->sst_cp_support = cp_cap;
98 		ctdp_level->sst_cp_enabled = cp_state;
99 	}
100 
101 	debug_printf(
102 		"cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
103 		id->cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
104 		ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
105 
106 	return 0;
107 }
108 
isst_get_tdp_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)109 int isst_get_tdp_info(struct isst_id *id, int config_index,
110 		      struct isst_pkg_ctdp_level_info *ctdp_level)
111 {
112 	unsigned int resp;
113 	int ret;
114 
115 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
116 				     0, config_index, &resp);
117 	if (ret) {
118 		isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
119 		return ret;
120 	}
121 
122 	ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
123 	ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
124 
125 	debug_printf(
126 		"cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
127 		id->cpu, config_index, resp, ctdp_level->tdp_ratio,
128 		ctdp_level->pkg_tdp);
129 	return 0;
130 }
131 
isst_get_pwr_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)132 int isst_get_pwr_info(struct isst_id *id, int config_index,
133 		      struct isst_pkg_ctdp_level_info *ctdp_level)
134 {
135 	unsigned int resp;
136 	int ret;
137 
138 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
139 				     0, config_index, &resp);
140 	if (ret)
141 		return ret;
142 
143 	ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
144 	ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
145 
146 	debug_printf(
147 		"cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
148 		id->cpu, config_index, resp, ctdp_level->pkg_max_power,
149 		ctdp_level->pkg_min_power);
150 
151 	return 0;
152 }
153 
isst_get_uncore_p0_p1_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)154 void isst_get_uncore_p0_p1_info(struct isst_id *id, int config_index,
155 				struct isst_pkg_ctdp_level_info *ctdp_level)
156 {
157 	unsigned int resp;
158 	int ret;
159 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
160 				     CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
161 				     config_index, &resp);
162 	if (ret) {
163 		ctdp_level->uncore_p0 = 0;
164 		ctdp_level->uncore_p1 = 0;
165 		return;
166 	}
167 
168 	ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
169 	ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
170 	debug_printf(
171 		"cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
172 		id->cpu, config_index, resp, ctdp_level->uncore_p0,
173 		ctdp_level->uncore_p1);
174 }
175 
isst_get_p1_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)176 void isst_get_p1_info(struct isst_id *id, int config_index,
177 		      struct isst_pkg_ctdp_level_info *ctdp_level)
178 {
179 	unsigned int resp;
180 	int ret;
181 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
182 				     config_index, &resp);
183 	if (ret) {
184 		ctdp_level->sse_p1 = 0;
185 		ctdp_level->avx2_p1 = 0;
186 		ctdp_level->avx512_p1 = 0;
187 		return;
188 	}
189 
190 	ctdp_level->sse_p1 = resp & GENMASK(7, 0);
191 	ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
192 	ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
193 	debug_printf(
194 		"cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d\n",
195 		id->cpu, config_index, resp, ctdp_level->sse_p1,
196 		ctdp_level->avx2_p1, ctdp_level->avx512_p1);
197 }
198 
isst_get_uncore_mem_freq(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)199 void isst_get_uncore_mem_freq(struct isst_id *id, int config_index,
200 			      struct isst_pkg_ctdp_level_info *ctdp_level)
201 {
202 	unsigned int resp;
203 	int ret;
204 
205 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
206 				     0, config_index, &resp);
207 	if (ret) {
208 		ctdp_level->mem_freq = 0;
209 		return;
210 	}
211 
212 	ctdp_level->mem_freq = resp & GENMASK(7, 0);
213 	if (is_spr_platform()) {
214 		ctdp_level->mem_freq *= 200;
215 	} else if (is_icx_platform()) {
216 		if (ctdp_level->mem_freq < 7) {
217 			ctdp_level->mem_freq = (12 - ctdp_level->mem_freq) * 133.33 * 2 * 10;
218 			ctdp_level->mem_freq /= 10;
219 			if (ctdp_level->mem_freq % 10 > 5)
220 				ctdp_level->mem_freq++;
221 		} else {
222 			ctdp_level->mem_freq = 0;
223 		}
224 	} else {
225 		ctdp_level->mem_freq = 0;
226 	}
227 	debug_printf(
228 		"cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
229 		id->cpu, config_index, resp, ctdp_level->mem_freq);
230 }
231 
isst_get_tjmax_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)232 int isst_get_tjmax_info(struct isst_id *id, int config_index,
233 			struct isst_pkg_ctdp_level_info *ctdp_level)
234 {
235 	unsigned int resp;
236 	int ret;
237 
238 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
239 				     0, config_index, &resp);
240 	if (ret)
241 		return ret;
242 
243 	ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
244 
245 	debug_printf(
246 		"cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
247 		id->cpu, config_index, resp, ctdp_level->t_proc_hot);
248 
249 	return 0;
250 }
251 
isst_get_coremask_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)252 int isst_get_coremask_info(struct isst_id *id, int config_index,
253 			   struct isst_pkg_ctdp_level_info *ctdp_level)
254 {
255 	unsigned int resp;
256 	int i, ret;
257 
258 	ctdp_level->cpu_count = 0;
259 	for (i = 0; i < 2; ++i) {
260 		unsigned long long mask;
261 		int cpu_count = 0;
262 
263 		ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
264 					     CONFIG_TDP_GET_CORE_MASK, 0,
265 					     (i << 8) | config_index, &resp);
266 		if (ret)
267 			return ret;
268 
269 		debug_printf(
270 			"cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
271 			id->cpu, config_index, i, resp);
272 
273 		mask = (unsigned long long)resp << (32 * i);
274 		set_cpu_mask_from_punit_coremask(id, mask,
275 						 ctdp_level->core_cpumask_size,
276 						 ctdp_level->core_cpumask,
277 						 &cpu_count);
278 		ctdp_level->cpu_count += cpu_count;
279 		debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", id->cpu,
280 			     config_index, i, ctdp_level->cpu_count);
281 	}
282 
283 	return 0;
284 }
285 
isst_get_get_trl_from_msr(struct isst_id * id,int * trl)286 int isst_get_get_trl_from_msr(struct isst_id *id, int *trl)
287 {
288 	unsigned long long msr_trl;
289 	int ret;
290 
291 	ret = isst_send_msr_command(id->cpu, 0x1AD, 0, &msr_trl);
292 	if (ret)
293 		return ret;
294 
295 	trl[0] = msr_trl & GENMASK(7, 0);
296 	trl[1] = (msr_trl & GENMASK(15, 8)) >> 8;
297 	trl[2] = (msr_trl & GENMASK(23, 16)) >> 16;
298 	trl[3] = (msr_trl & GENMASK(31, 24)) >> 24;
299 	trl[4] = (msr_trl & GENMASK(39, 32)) >> 32;
300 	trl[5] = (msr_trl & GENMASK(47, 40)) >> 40;
301 	trl[6] = (msr_trl & GENMASK(55, 48)) >> 48;
302 	trl[7] = (msr_trl & GENMASK(63, 56)) >> 56;
303 
304 	return 0;
305 }
306 
isst_get_get_trl(struct isst_id * id,int level,int avx_level,int * trl)307 int isst_get_get_trl(struct isst_id *id, int level, int avx_level, int *trl)
308 {
309 	unsigned int req, resp;
310 	int ret;
311 
312 	req = level | (avx_level << 16);
313 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
314 				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
315 				     &resp);
316 	if (ret)
317 		return ret;
318 
319 	debug_printf(
320 		"cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
321 		id->cpu, req, resp);
322 
323 	trl[0] = resp & GENMASK(7, 0);
324 	trl[1] = (resp & GENMASK(15, 8)) >> 8;
325 	trl[2] = (resp & GENMASK(23, 16)) >> 16;
326 	trl[3] = (resp & GENMASK(31, 24)) >> 24;
327 
328 	req = level | BIT(8) | (avx_level << 16);
329 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
330 				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
331 				     &resp);
332 	if (ret)
333 		return ret;
334 
335 	debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", id->cpu,
336 		     req, resp);
337 
338 	trl[4] = resp & GENMASK(7, 0);
339 	trl[5] = (resp & GENMASK(15, 8)) >> 8;
340 	trl[6] = (resp & GENMASK(23, 16)) >> 16;
341 	trl[7] = (resp & GENMASK(31, 24)) >> 24;
342 
343 	return 0;
344 }
345 
isst_get_trl_bucket_info(struct isst_id * id,unsigned long long * buckets_info)346 int isst_get_trl_bucket_info(struct isst_id *id, unsigned long long *buckets_info)
347 {
348 	int ret;
349 
350 	debug_printf("cpu:%d bucket info via MSR\n", id->cpu);
351 
352 	*buckets_info = 0;
353 
354 	ret = isst_send_msr_command(id->cpu, 0x1ae, 0, buckets_info);
355 	if (ret)
356 		return ret;
357 
358 	debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", id->cpu,
359 		     *buckets_info);
360 
361 	return 0;
362 }
363 
isst_set_tdp_level(struct isst_id * id,int tdp_level)364 int isst_set_tdp_level(struct isst_id *id, int tdp_level)
365 {
366 	unsigned int resp;
367 	int ret;
368 
369 
370 	if (isst_get_config_tdp_lock_status(id)) {
371 		isst_display_error_info_message(1, "TDP is locked", 0, 0);
372 		return -1;
373 
374 	}
375 
376 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
377 				     tdp_level, &resp);
378 	if (ret) {
379 		isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);
380 		return ret;
381 	}
382 
383 	return 0;
384 }
385 
isst_get_pbf_info(struct isst_id * id,int level,struct isst_pbf_info * pbf_info)386 int isst_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info)
387 {
388 	struct isst_pkg_ctdp_level_info ctdp_level;
389 	struct isst_pkg_ctdp pkg_dev;
390 	int i, ret, max_punit_core, max_mask_index;
391 	unsigned int req, resp;
392 
393 	ret = isst_get_ctdp_levels(id, &pkg_dev);
394 	if (ret) {
395 		isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
396 		return ret;
397 	}
398 
399 	if (level > pkg_dev.levels) {
400 		isst_display_error_info_message(1, "Invalid level", 1, level);
401 		return -1;
402 	}
403 
404 	ret = isst_get_ctdp_control(id, level, &ctdp_level);
405 	if (ret)
406 		return ret;
407 
408 	if (!ctdp_level.pbf_support) {
409 		isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, level);
410 		return -1;
411 	}
412 
413 	pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
414 
415 	max_punit_core = get_max_punit_core_id(id);
416 	max_mask_index = max_punit_core > 32 ? 2 : 1;
417 
418 	for (i = 0; i < max_mask_index; ++i) {
419 		unsigned long long mask;
420 		int count;
421 
422 		ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
423 					     CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
424 					     0, (i << 8) | level, &resp);
425 		if (ret)
426 			break;
427 
428 		debug_printf(
429 			"cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
430 			id->cpu, resp);
431 
432 		mask = (unsigned long long)resp << (32 * i);
433 		set_cpu_mask_from_punit_coremask(id, mask,
434 						 pbf_info->core_cpumask_size,
435 						 pbf_info->core_cpumask,
436 						 &count);
437 	}
438 
439 	req = level;
440 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
441 				     CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
442 				     &resp);
443 	if (ret)
444 		return ret;
445 
446 	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", id->cpu,
447 		     resp);
448 
449 	pbf_info->p1_low = resp & 0xff;
450 	pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
451 
452 	req = level;
453 	ret = isst_send_mbox_command(
454 		id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
455 	if (ret)
456 		return ret;
457 
458 	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", id->cpu, resp);
459 
460 	pbf_info->tdp = resp & 0xffff;
461 
462 	req = level;
463 	ret = isst_send_mbox_command(
464 		id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
465 	if (ret)
466 		return ret;
467 
468 	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", id->cpu,
469 		     resp);
470 	pbf_info->t_control = (resp >> 8) & 0xff;
471 	pbf_info->t_prochot = resp & 0xff;
472 
473 	return 0;
474 }
475 
isst_get_pbf_info_complete(struct isst_pbf_info * pbf_info)476 void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info)
477 {
478 	free_cpu_set(pbf_info->core_cpumask);
479 }
480 
isst_set_pbf_fact_status(struct isst_id * id,int pbf,int enable)481 int isst_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
482 {
483 	struct isst_pkg_ctdp pkg_dev;
484 	struct isst_pkg_ctdp_level_info ctdp_level;
485 	int current_level;
486 	unsigned int req = 0, resp;
487 	int ret;
488 
489 	ret = isst_get_ctdp_levels(id, &pkg_dev);
490 	if (ret)
491 		debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
492 
493 	current_level = pkg_dev.current_level;
494 
495 	ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
496 	if (ret)
497 		return ret;
498 
499 	if (pbf) {
500 		if (ctdp_level.fact_enabled)
501 			req = BIT(16);
502 
503 		if (enable)
504 			req |= BIT(17);
505 		else
506 			req &= ~BIT(17);
507 	} else {
508 
509 		if (enable && !ctdp_level.sst_cp_enabled)
510 			isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);
511 
512 		if (ctdp_level.pbf_enabled)
513 			req = BIT(17);
514 
515 		if (enable)
516 			req |= BIT(16);
517 		else
518 			req &= ~BIT(16);
519 	}
520 
521 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
522 				     CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
523 	if (ret)
524 		return ret;
525 
526 	debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
527 		     id->cpu, pbf, req);
528 
529 	return 0;
530 }
531 
isst_get_fact_bucket_info(struct isst_id * id,int level,struct isst_fact_bucket_info * bucket_info)532 int isst_get_fact_bucket_info(struct isst_id *id, int level,
533 			      struct isst_fact_bucket_info *bucket_info)
534 {
535 	unsigned int resp;
536 	int i, k, ret;
537 
538 	for (i = 0; i < 2; ++i) {
539 		int j;
540 
541 		ret = isst_send_mbox_command(
542 			id->cpu, CONFIG_TDP,
543 			CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
544 			(i << 8) | level, &resp);
545 		if (ret)
546 			return ret;
547 
548 		debug_printf(
549 			"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
550 			id->cpu, i, level, resp);
551 
552 		for (j = 0; j < 4; ++j) {
553 			bucket_info[j + (i * 4)].high_priority_cores_count =
554 				(resp >> (j * 8)) & 0xff;
555 		}
556 	}
557 
558 	for (k = 0; k < 3; ++k) {
559 		for (i = 0; i < 2; ++i) {
560 			int j;
561 
562 			ret = isst_send_mbox_command(
563 				id->cpu, CONFIG_TDP,
564 				CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
565 				(k << 16) | (i << 8) | level, &resp);
566 			if (ret)
567 				return ret;
568 
569 			debug_printf(
570 				"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
571 				id->cpu, i, level, k, resp);
572 
573 			for (j = 0; j < 4; ++j) {
574 				switch (k) {
575 				case 0:
576 					bucket_info[j + (i * 4)].sse_trl =
577 						(resp >> (j * 8)) & 0xff;
578 					break;
579 				case 1:
580 					bucket_info[j + (i * 4)].avx_trl =
581 						(resp >> (j * 8)) & 0xff;
582 					break;
583 				case 2:
584 					bucket_info[j + (i * 4)].avx512_trl =
585 						(resp >> (j * 8)) & 0xff;
586 					break;
587 				default:
588 					break;
589 				}
590 			}
591 		}
592 	}
593 
594 	return 0;
595 }
596 
isst_get_fact_info(struct isst_id * id,int level,int fact_bucket,struct isst_fact_info * fact_info)597 int isst_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info)
598 {
599 	struct isst_pkg_ctdp_level_info ctdp_level;
600 	struct isst_pkg_ctdp pkg_dev;
601 	unsigned int resp;
602 	int j, ret, print;
603 
604 	ret = isst_get_ctdp_levels(id, &pkg_dev);
605 	if (ret) {
606 		isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
607 		return ret;
608 	}
609 
610 	if (level > pkg_dev.levels) {
611 		isst_display_error_info_message(1, "Invalid level", 1, level);
612 		return -1;
613 	}
614 
615 	ret = isst_get_ctdp_control(id, level, &ctdp_level);
616 	if (ret)
617 		return ret;
618 
619 	if (!ctdp_level.fact_support) {
620 		isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, level);
621 		return -1;
622 	}
623 
624 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
625 				     CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
626 				     level, &resp);
627 	if (ret)
628 		return ret;
629 
630 	debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
631 		     id->cpu, resp);
632 
633 	fact_info->lp_clipping_ratio_license_sse = resp & 0xff;
634 	fact_info->lp_clipping_ratio_license_avx2 = (resp >> 8) & 0xff;
635 	fact_info->lp_clipping_ratio_license_avx512 = (resp >> 16) & 0xff;
636 
637 	ret = isst_get_fact_bucket_info(id, level, fact_info->bucket_info);
638 	if (ret)
639 		return ret;
640 
641 	print = 0;
642 	for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
643 		if (fact_bucket != 0xff && fact_bucket != j)
644 			continue;
645 
646 		if (!fact_info->bucket_info[j].high_priority_cores_count)
647 			break;
648 
649 		print = 1;
650 	}
651 	if (!print) {
652 		isst_display_error_info_message(1, "Invalid bucket", 0, 0);
653 		return -1;
654 	}
655 
656 	return 0;
657 }
658 
isst_get_trl(struct isst_id * id,unsigned long long * trl)659 int isst_get_trl(struct isst_id *id, unsigned long long *trl)
660 {
661 	int ret;
662 
663 	ret = isst_send_msr_command(id->cpu, 0x1AD, 0, trl);
664 	if (ret)
665 		return ret;
666 
667 	return 0;
668 }
669 
isst_set_trl(struct isst_id * id,unsigned long long trl)670 int isst_set_trl(struct isst_id *id, unsigned long long trl)
671 {
672 	int ret;
673 
674 	if (!trl)
675 		trl = 0xFFFFFFFFFFFFFFFFULL;
676 
677 	ret = isst_send_msr_command(id->cpu, 0x1AD, 1, &trl);
678 	if (ret)
679 		return ret;
680 
681 	return 0;
682 }
683 
isst_set_trl_from_current_tdp(struct isst_id * id,unsigned long long trl)684 int isst_set_trl_from_current_tdp(struct isst_id *id, unsigned long long trl)
685 {
686 	unsigned long long msr_trl;
687 	int ret;
688 
689 	if (trl) {
690 		msr_trl = trl;
691 	} else {
692 		struct isst_pkg_ctdp pkg_dev;
693 		int trl[8];
694 		int i;
695 
696 		ret = isst_get_ctdp_levels(id, &pkg_dev);
697 		if (ret)
698 			return ret;
699 
700 		ret = isst_get_get_trl(id, pkg_dev.current_level, 0, trl);
701 		if (ret)
702 			return ret;
703 
704 		msr_trl = 0;
705 		for (i = 0; i < 8; ++i) {
706 			unsigned long long _trl = trl[i];
707 
708 			msr_trl |= (_trl << (i * 8));
709 		}
710 	}
711 	ret = isst_send_msr_command(id->cpu, 0x1AD, 1, &msr_trl);
712 	if (ret)
713 		return ret;
714 
715 	return 0;
716 }
717 
718 /* Return 1 if locked */
isst_get_config_tdp_lock_status(struct isst_id * id)719 int isst_get_config_tdp_lock_status(struct isst_id *id)
720 {
721 	unsigned long long tdp_control = 0;
722 	int ret;
723 
724 	ret = isst_send_msr_command(id->cpu, 0x64b, 0, &tdp_control);
725 	if (ret)
726 		return ret;
727 
728 	ret = !!(tdp_control & BIT(31));
729 
730 	return ret;
731 }
732 
isst_get_process_ctdp_complete(struct isst_id * id,struct isst_pkg_ctdp * pkg_dev)733 void isst_get_process_ctdp_complete(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
734 {
735 	int i;
736 
737 	if (!pkg_dev->processed)
738 		return;
739 
740 	for (i = 0; i < pkg_dev->levels; ++i) {
741 		struct isst_pkg_ctdp_level_info *ctdp_level;
742 
743 		ctdp_level = &pkg_dev->ctdp_level[i];
744 		if (ctdp_level->pbf_support)
745 			free_cpu_set(ctdp_level->pbf_info.core_cpumask);
746 		free_cpu_set(ctdp_level->core_cpumask);
747 	}
748 }
749 
isst_get_process_ctdp(struct isst_id * id,int tdp_level,struct isst_pkg_ctdp * pkg_dev)750 int isst_get_process_ctdp(struct isst_id *id, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
751 {
752 	int i, ret, valid = 0;
753 
754 	if (pkg_dev->processed)
755 		return 0;
756 
757 	ret = isst_get_ctdp_levels(id, pkg_dev);
758 	if (ret)
759 		return ret;
760 
761 	debug_printf("cpu: %d ctdp enable:%d current level: %d levels:%d\n",
762 		     id->cpu, pkg_dev->enabled, pkg_dev->current_level,
763 		     pkg_dev->levels);
764 
765 	if (tdp_level != 0xff && tdp_level > pkg_dev->levels) {
766 		isst_display_error_info_message(1, "Invalid level", 0, 0);
767 		return -1;
768 	}
769 
770 	if (!pkg_dev->enabled)
771 		isst_display_error_info_message(0, "perf-profile feature is not supported, just base-config level 0 is valid", 0, 0);
772 
773 	for (i = 0; i <= pkg_dev->levels; ++i) {
774 		struct isst_pkg_ctdp_level_info *ctdp_level;
775 
776 		if (tdp_level != 0xff && i != tdp_level)
777 			continue;
778 
779 		debug_printf("cpu:%d Get Information for TDP level:%d\n", id->cpu,
780 			     i);
781 		ctdp_level = &pkg_dev->ctdp_level[i];
782 
783 		ctdp_level->level = i;
784 		ctdp_level->control_cpu = id->cpu;
785 		ctdp_level->pkg_id = id->pkg;
786 		ctdp_level->die_id = id->die;
787 
788 		ret = isst_get_ctdp_control(id, i, ctdp_level);
789 		if (ret)
790 			continue;
791 
792 		valid = 1;
793 		pkg_dev->processed = 1;
794 		ctdp_level->processed = 1;
795 
796 		if (ctdp_level->pbf_support) {
797 			ret = isst_get_pbf_info(id, i, &ctdp_level->pbf_info);
798 			if (!ret)
799 				ctdp_level->pbf_found = 1;
800 		}
801 
802 		if (ctdp_level->fact_support) {
803 			ret = isst_get_fact_info(id, i, 0xff,
804 						 &ctdp_level->fact_info);
805 			if (ret)
806 				return ret;
807 		}
808 
809 		if (!pkg_dev->enabled && is_skx_based_platform()) {
810 			int freq;
811 
812 			freq = get_cpufreq_base_freq(id->cpu);
813 			if (freq > 0) {
814 				ctdp_level->sse_p1 = freq / 100000;
815 				ctdp_level->tdp_ratio = ctdp_level->sse_p1;
816 			}
817 
818 			isst_get_get_trl_from_msr(id, ctdp_level->trl_sse_active_cores);
819 			isst_get_trl_bucket_info(id, &ctdp_level->buckets_info);
820 			continue;
821 		}
822 
823 		ret = isst_get_tdp_info(id, i, ctdp_level);
824 		if (ret)
825 			return ret;
826 
827 		ret = isst_get_pwr_info(id, i, ctdp_level);
828 		if (ret)
829 			return ret;
830 
831 		ret = isst_get_tjmax_info(id, i, ctdp_level);
832 		if (ret)
833 			return ret;
834 
835 		ctdp_level->core_cpumask_size =
836 			alloc_cpu_set(&ctdp_level->core_cpumask);
837 		ret = isst_get_coremask_info(id, i, ctdp_level);
838 		if (ret)
839 			return ret;
840 
841 		ret = isst_get_trl_bucket_info(id, &ctdp_level->buckets_info);
842 		if (ret)
843 			return ret;
844 
845 		ret = isst_get_get_trl(id, i, 0,
846 				       ctdp_level->trl_sse_active_cores);
847 		if (ret)
848 			return ret;
849 
850 		ret = isst_get_get_trl(id, i, 1,
851 				       ctdp_level->trl_avx_active_cores);
852 		if (ret)
853 			return ret;
854 
855 		ret = isst_get_get_trl(id, i, 2,
856 				       ctdp_level->trl_avx_512_active_cores);
857 		if (ret)
858 			return ret;
859 
860 		isst_get_uncore_p0_p1_info(id, i, ctdp_level);
861 		isst_get_p1_info(id, i, ctdp_level);
862 		isst_get_uncore_mem_freq(id, i, ctdp_level);
863 	}
864 
865 	if (!valid)
866 		isst_display_error_info_message(0, "Invalid level, Can't get TDP control information at specified levels on cpu", 1, id->cpu);
867 
868 	return 0;
869 }
870 
isst_clos_get_clos_information(struct isst_id * id,int * enable,int * type)871 int isst_clos_get_clos_information(struct isst_id *id, int *enable, int *type)
872 {
873 	unsigned int resp;
874 	int ret;
875 
876 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
877 				     &resp);
878 	if (ret)
879 		return ret;
880 
881 	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
882 
883 	if (resp & BIT(1))
884 		*enable = 1;
885 	else
886 		*enable = 0;
887 
888 	if (resp & BIT(2))
889 		*type = 1;
890 	else
891 		*type = 0;
892 
893 	return 0;
894 }
895 
isst_pm_qos_config(struct isst_id * id,int enable_clos,int priority_type)896 int isst_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type)
897 {
898 	unsigned int req, resp;
899 	int ret;
900 
901 	if (!enable_clos) {
902 		struct isst_pkg_ctdp pkg_dev;
903 		struct isst_pkg_ctdp_level_info ctdp_level;
904 
905 		ret = isst_get_ctdp_levels(id, &pkg_dev);
906 		if (ret) {
907 			debug_printf("isst_get_ctdp_levels\n");
908 			return ret;
909 		}
910 
911 		ret = isst_get_ctdp_control(id, pkg_dev.current_level,
912 					    &ctdp_level);
913 		if (ret)
914 			return ret;
915 
916 		if (ctdp_level.fact_enabled) {
917 			isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
918 			return -EINVAL;
919 		}
920 		ret = isst_write_pm_config(id, 0);
921 		if (ret)
922 			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
923 	} else {
924 		ret = isst_write_pm_config(id, 1);
925 		if (ret)
926 			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
927 	}
928 
929 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
930 				     &resp);
931 	if (ret) {
932 		isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
933 		return ret;
934 	}
935 
936 	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
937 
938 	req = resp;
939 
940 	if (enable_clos)
941 		req = req | BIT(1);
942 	else
943 		req = req & ~BIT(1);
944 
945 	if (priority_type > 1)
946 		isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
947 
948 	if (priority_type)
949 		req = req | BIT(2);
950 	else
951 		req = req & ~BIT(2);
952 
953 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
954 				     BIT(MBOX_CMD_WRITE_BIT), req, &resp);
955 	if (ret)
956 		return ret;
957 
958 	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu,
959 		     priority_type, req);
960 
961 	return 0;
962 }
963 
isst_pm_get_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)964 int isst_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
965 {
966 	unsigned int resp;
967 	int ret;
968 
969 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
970 				     &resp);
971 	if (ret)
972 		return ret;
973 
974 	clos_config->epp = resp & 0x0f;
975 	clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
976 	clos_config->clos_min = (resp >> 8) & 0xff;
977 	clos_config->clos_max = (resp >> 16) & 0xff;
978 	clos_config->clos_desired = (resp >> 24) & 0xff;
979 
980 	return 0;
981 }
982 
isst_set_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)983 int isst_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
984 {
985 	unsigned int req, resp;
986 	unsigned int param;
987 	int ret;
988 
989 	req = clos_config->epp & 0x0f;
990 	req |= (clos_config->clos_prop_prio & 0x0f) << 4;
991 	req |= (clos_config->clos_min & 0xff) << 8;
992 	req |= (clos_config->clos_max & 0xff) << 16;
993 	req |= (clos_config->clos_desired & 0xff) << 24;
994 
995 	param = BIT(MBOX_CMD_WRITE_BIT) | clos;
996 
997 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
998 				     &resp);
999 	if (ret)
1000 		return ret;
1001 
1002 	debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req);
1003 
1004 	return 0;
1005 }
1006 
isst_clos_get_assoc_status(struct isst_id * id,int * clos_id)1007 int isst_clos_get_assoc_status(struct isst_id *id, int *clos_id)
1008 {
1009 	unsigned int resp;
1010 	unsigned int param;
1011 	int core_id, ret;
1012 
1013 	core_id = find_phy_core_num(id->cpu);
1014 	param = core_id;
1015 
1016 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
1017 				     &resp);
1018 	if (ret)
1019 		return ret;
1020 
1021 	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param,
1022 		     resp);
1023 	*clos_id = (resp >> 16) & 0x03;
1024 
1025 	return 0;
1026 }
1027 
isst_clos_associate(struct isst_id * id,int clos_id)1028 int isst_clos_associate(struct isst_id *id, int clos_id)
1029 {
1030 	unsigned int req, resp;
1031 	unsigned int param;
1032 	int core_id, ret;
1033 
1034 	req = (clos_id & 0x03) << 16;
1035 	core_id = find_phy_core_num(id->cpu);
1036 	param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
1037 
1038 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
1039 				     req, &resp);
1040 	if (ret)
1041 		return ret;
1042 
1043 	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->cpu, param,
1044 		     req);
1045 
1046 	return 0;
1047 }
1048