xref: /openbsd/sys/dev/pci/drm/i915/gt/intel_gt_sysfs_pm.c (revision d415bd75)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2022 Intel Corporation
4  */
5 
6 #include <drm/drm_device.h>
7 #include <linux/sysfs.h>
8 #include <linux/printk.h>
9 
10 #include "i915_drv.h"
11 #include "i915_reg.h"
12 #include "i915_sysfs.h"
13 #include "intel_gt.h"
14 #include "intel_gt_regs.h"
15 #include "intel_gt_sysfs.h"
16 #include "intel_gt_sysfs_pm.h"
17 #include "intel_pcode.h"
18 #include "intel_rc6.h"
19 #include "intel_rps.h"
20 
21 #ifdef notyet
22 
23 enum intel_gt_sysfs_op {
24 	INTEL_GT_SYSFS_MIN = 0,
25 	INTEL_GT_SYSFS_MAX,
26 };
27 
28 static int
29 sysfs_gt_attribute_w_func(struct kobject *kobj, struct attribute *attr,
30 			  int (func)(struct intel_gt *gt, u32 val), u32 val)
31 {
32 	struct intel_gt *gt;
33 	int ret;
34 
35 	if (!is_object_gt(kobj)) {
36 		int i;
37 		struct device *dev = kobj_to_dev(kobj);
38 		struct drm_i915_private *i915 = kdev_minor_to_i915(dev);
39 
40 		for_each_gt(gt, i915, i) {
41 			ret = func(gt, val);
42 			if (ret)
43 				break;
44 		}
45 	} else {
46 		gt = intel_gt_sysfs_get_drvdata(kobj, attr->name);
47 		ret = func(gt, val);
48 	}
49 
50 	return ret;
51 }
52 
53 static u32
54 sysfs_gt_attribute_r_func(struct kobject *kobj, struct attribute *attr,
55 			  u32 (func)(struct intel_gt *gt),
56 			  enum intel_gt_sysfs_op op)
57 {
58 	struct intel_gt *gt;
59 	u32 ret;
60 
61 	ret = (op == INTEL_GT_SYSFS_MAX) ? 0 : (u32) -1;
62 
63 	if (!is_object_gt(kobj)) {
64 		int i;
65 		struct device *dev = kobj_to_dev(kobj);
66 		struct drm_i915_private *i915 = kdev_minor_to_i915(dev);
67 
68 		for_each_gt(gt, i915, i) {
69 			u32 val = func(gt);
70 
71 			switch (op) {
72 			case INTEL_GT_SYSFS_MIN:
73 				if (val < ret)
74 					ret = val;
75 				break;
76 
77 			case INTEL_GT_SYSFS_MAX:
78 				if (val > ret)
79 					ret = val;
80 				break;
81 			}
82 		}
83 	} else {
84 		gt = intel_gt_sysfs_get_drvdata(kobj, attr->name);
85 		ret = func(gt);
86 	}
87 
88 	return ret;
89 }
90 
91 /* RC6 interfaces will show the minimum RC6 residency value */
92 #define sysfs_gt_attribute_r_min_func(d, a, f) \
93 		sysfs_gt_attribute_r_func(d, a, f, INTEL_GT_SYSFS_MIN)
94 
95 /* Frequency interfaces will show the maximum frequency value */
96 #define sysfs_gt_attribute_r_max_func(d, a, f) \
97 		sysfs_gt_attribute_r_func(d, a, f, INTEL_GT_SYSFS_MAX)
98 
99 #define INTEL_GT_SYSFS_SHOW(_name, _attr_type)							\
100 	static ssize_t _name##_show_common(struct kobject *kobj,				\
101 					   struct attribute *attr, char *buff)			\
102 	{											\
103 		u32 val = sysfs_gt_attribute_r_##_attr_type##_func(kobj, attr,			\
104 								   __##_name##_show);		\
105 												\
106 		return sysfs_emit(buff, "%u\n", val);						\
107 	}											\
108 	static ssize_t _name##_show(struct kobject *kobj,					\
109 				    struct kobj_attribute *attr, char *buff)			\
110 	{											\
111 		return _name ##_show_common(kobj, &attr->attr, buff);				\
112 	}											\
113 	static ssize_t _name##_dev_show(struct device *dev,					\
114 					struct device_attribute *attr, char *buff)		\
115 	{											\
116 		return _name##_show_common(&dev->kobj, &attr->attr, buff);			\
117 	}
118 
119 #define INTEL_GT_SYSFS_STORE(_name, _func)						\
120 	static ssize_t _name##_store_common(struct kobject *kobj,			\
121 					    struct attribute *attr,			\
122 					    const char *buff, size_t count)		\
123 	{										\
124 		int ret;								\
125 		u32 val;								\
126 											\
127 		ret = kstrtou32(buff, 0, &val);						\
128 		if (ret)								\
129 			return ret;							\
130 											\
131 		ret = sysfs_gt_attribute_w_func(kobj, attr, _func, val);		\
132 											\
133 		return ret ?: count;							\
134 	}										\
135 	static ssize_t _name##_store(struct kobject *kobj,				\
136 				     struct kobj_attribute *attr, const char *buff,	\
137 				     size_t count)					\
138 	{										\
139 		return _name##_store_common(kobj, &attr->attr, buff, count);		\
140 	}										\
141 	static ssize_t _name##_dev_store(struct device *dev,				\
142 					 struct device_attribute *attr,			\
143 					 const char *buff, size_t count)		\
144 	{										\
145 		return _name##_store_common(&dev->kobj, &attr->attr, buff, count);	\
146 	}
147 
148 #define INTEL_GT_SYSFS_SHOW_MAX(_name) INTEL_GT_SYSFS_SHOW(_name, max)
149 #define INTEL_GT_SYSFS_SHOW_MIN(_name) INTEL_GT_SYSFS_SHOW(_name, min)
150 
151 #define INTEL_GT_ATTR_RW(_name) \
152 	static struct kobj_attribute attr_##_name = __ATTR_RW(_name)
153 
154 #define INTEL_GT_ATTR_RO(_name) \
155 	static struct kobj_attribute attr_##_name = __ATTR_RO(_name)
156 
157 #define INTEL_GT_DUAL_ATTR_RW(_name) \
158 	static struct device_attribute dev_attr_##_name = __ATTR(_name, 0644,		\
159 								 _name##_dev_show,	\
160 								 _name##_dev_store);	\
161 	INTEL_GT_ATTR_RW(_name)
162 
163 #define INTEL_GT_DUAL_ATTR_RO(_name) \
164 	static struct device_attribute dev_attr_##_name = __ATTR(_name, 0444,		\
165 								 _name##_dev_show,	\
166 								 NULL);			\
167 	INTEL_GT_ATTR_RO(_name)
168 
169 #ifdef CONFIG_PM
170 static u32 get_residency(struct intel_gt *gt, i915_reg_t reg)
171 {
172 	intel_wakeref_t wakeref;
173 	u64 res = 0;
174 
175 	with_intel_runtime_pm(gt->uncore->rpm, wakeref)
176 		res = intel_rc6_residency_us(&gt->rc6, reg);
177 
178 	return DIV_ROUND_CLOSEST_ULL(res, 1000);
179 }
180 
181 static u8 get_rc6_mask(struct intel_gt *gt)
182 {
183 	u8 mask = 0;
184 
185 	if (HAS_RC6(gt->i915))
186 		mask |= BIT(0);
187 	if (HAS_RC6p(gt->i915))
188 		mask |= BIT(1);
189 	if (HAS_RC6pp(gt->i915))
190 		mask |= BIT(2);
191 
192 	return mask;
193 }
194 
195 static ssize_t rc6_enable_show(struct kobject *kobj,
196 			       struct kobj_attribute *attr,
197 			       char *buff)
198 {
199 	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
200 
201 	return sysfs_emit(buff, "%x\n", get_rc6_mask(gt));
202 }
203 
204 static ssize_t rc6_enable_dev_show(struct device *dev,
205 				   struct device_attribute *attr,
206 				   char *buff)
207 {
208 	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(&dev->kobj, attr->attr.name);
209 
210 	return sysfs_emit(buff, "%x\n", get_rc6_mask(gt));
211 }
212 
213 static u32 __rc6_residency_ms_show(struct intel_gt *gt)
214 {
215 	return get_residency(gt, GEN6_GT_GFX_RC6);
216 }
217 
218 static u32 __rc6p_residency_ms_show(struct intel_gt *gt)
219 {
220 	return get_residency(gt, GEN6_GT_GFX_RC6p);
221 }
222 
223 static u32 __rc6pp_residency_ms_show(struct intel_gt *gt)
224 {
225 	return get_residency(gt, GEN6_GT_GFX_RC6pp);
226 }
227 
228 static u32 __media_rc6_residency_ms_show(struct intel_gt *gt)
229 {
230 	return get_residency(gt, VLV_GT_MEDIA_RC6);
231 }
232 
233 INTEL_GT_SYSFS_SHOW_MIN(rc6_residency_ms);
234 INTEL_GT_SYSFS_SHOW_MIN(rc6p_residency_ms);
235 INTEL_GT_SYSFS_SHOW_MIN(rc6pp_residency_ms);
236 INTEL_GT_SYSFS_SHOW_MIN(media_rc6_residency_ms);
237 
238 INTEL_GT_DUAL_ATTR_RO(rc6_enable);
239 INTEL_GT_DUAL_ATTR_RO(rc6_residency_ms);
240 INTEL_GT_DUAL_ATTR_RO(rc6p_residency_ms);
241 INTEL_GT_DUAL_ATTR_RO(rc6pp_residency_ms);
242 INTEL_GT_DUAL_ATTR_RO(media_rc6_residency_ms);
243 
244 static struct attribute *rc6_attrs[] = {
245 	&attr_rc6_enable.attr,
246 	&attr_rc6_residency_ms.attr,
247 	NULL
248 };
249 
250 static struct attribute *rc6p_attrs[] = {
251 	&attr_rc6p_residency_ms.attr,
252 	&attr_rc6pp_residency_ms.attr,
253 	NULL
254 };
255 
256 static struct attribute *media_rc6_attrs[] = {
257 	&attr_media_rc6_residency_ms.attr,
258 	NULL
259 };
260 
261 static struct attribute *rc6_dev_attrs[] = {
262 	&dev_attr_rc6_enable.attr,
263 	&dev_attr_rc6_residency_ms.attr,
264 	NULL
265 };
266 
267 static struct attribute *rc6p_dev_attrs[] = {
268 	&dev_attr_rc6p_residency_ms.attr,
269 	&dev_attr_rc6pp_residency_ms.attr,
270 	NULL
271 };
272 
273 static struct attribute *media_rc6_dev_attrs[] = {
274 	&dev_attr_media_rc6_residency_ms.attr,
275 	NULL
276 };
277 
278 static const struct attribute_group rc6_attr_group[] = {
279 	{ .attrs = rc6_attrs, },
280 	{ .name = power_group_name, .attrs = rc6_dev_attrs, },
281 };
282 
283 static const struct attribute_group rc6p_attr_group[] = {
284 	{ .attrs = rc6p_attrs, },
285 	{ .name = power_group_name, .attrs = rc6p_dev_attrs, },
286 };
287 
288 static const struct attribute_group media_rc6_attr_group[] = {
289 	{ .attrs = media_rc6_attrs, },
290 	{ .name = power_group_name, .attrs = media_rc6_dev_attrs, },
291 };
292 
293 static int __intel_gt_sysfs_create_group(struct kobject *kobj,
294 					 const struct attribute_group *grp)
295 {
296 	return is_object_gt(kobj) ?
297 	       sysfs_create_group(kobj, &grp[0]) :
298 	       sysfs_merge_group(kobj, &grp[1]);
299 }
300 
301 static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
302 {
303 	int ret;
304 
305 	if (!HAS_RC6(gt->i915))
306 		return;
307 
308 	ret = __intel_gt_sysfs_create_group(kobj, rc6_attr_group);
309 	if (ret)
310 		drm_warn(&gt->i915->drm,
311 			 "failed to create gt%u RC6 sysfs files (%pe)\n",
312 			 gt->info.id, ERR_PTR(ret));
313 
314 	/*
315 	 * cannot use the is_visible() attribute because
316 	 * the upper object inherits from the parent group.
317 	 */
318 	if (HAS_RC6p(gt->i915)) {
319 		ret = __intel_gt_sysfs_create_group(kobj, rc6p_attr_group);
320 		if (ret)
321 			drm_warn(&gt->i915->drm,
322 				 "failed to create gt%u RC6p sysfs files (%pe)\n",
323 				 gt->info.id, ERR_PTR(ret));
324 	}
325 
326 	if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) {
327 		ret = __intel_gt_sysfs_create_group(kobj, media_rc6_attr_group);
328 		if (ret)
329 			drm_warn(&gt->i915->drm,
330 				 "failed to create media %u RC6 sysfs files (%pe)\n",
331 				 gt->info.id, ERR_PTR(ret));
332 	}
333 }
334 #else
335 static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj)
336 {
337 }
338 #endif /* CONFIG_PM */
339 
340 static u32 __act_freq_mhz_show(struct intel_gt *gt)
341 {
342 	return intel_rps_read_actual_frequency(&gt->rps);
343 }
344 
345 static u32 __cur_freq_mhz_show(struct intel_gt *gt)
346 {
347 	return intel_rps_get_requested_frequency(&gt->rps);
348 }
349 
350 static u32 __boost_freq_mhz_show(struct intel_gt *gt)
351 {
352 	return intel_rps_get_boost_frequency(&gt->rps);
353 }
354 
355 static int __boost_freq_mhz_store(struct intel_gt *gt, u32 val)
356 {
357 	return intel_rps_set_boost_frequency(&gt->rps, val);
358 }
359 
360 static u32 __RP0_freq_mhz_show(struct intel_gt *gt)
361 {
362 	return intel_rps_get_rp0_frequency(&gt->rps);
363 }
364 
365 static u32 __RPn_freq_mhz_show(struct intel_gt *gt)
366 {
367 	return intel_rps_get_rpn_frequency(&gt->rps);
368 }
369 
370 static u32 __RP1_freq_mhz_show(struct intel_gt *gt)
371 {
372 	return intel_rps_get_rp1_frequency(&gt->rps);
373 }
374 
375 static u32 __max_freq_mhz_show(struct intel_gt *gt)
376 {
377 	return intel_rps_get_max_frequency(&gt->rps);
378 }
379 
380 static int __set_max_freq(struct intel_gt *gt, u32 val)
381 {
382 	return intel_rps_set_max_frequency(&gt->rps, val);
383 }
384 
385 static u32 __min_freq_mhz_show(struct intel_gt *gt)
386 {
387 	return intel_rps_get_min_frequency(&gt->rps);
388 }
389 
390 static int __set_min_freq(struct intel_gt *gt, u32 val)
391 {
392 	return intel_rps_set_min_frequency(&gt->rps, val);
393 }
394 
395 static u32 __vlv_rpe_freq_mhz_show(struct intel_gt *gt)
396 {
397 	struct intel_rps *rps = &gt->rps;
398 
399 	return intel_gpu_freq(rps, rps->efficient_freq);
400 }
401 
402 INTEL_GT_SYSFS_SHOW_MAX(act_freq_mhz);
403 INTEL_GT_SYSFS_SHOW_MAX(boost_freq_mhz);
404 INTEL_GT_SYSFS_SHOW_MAX(cur_freq_mhz);
405 INTEL_GT_SYSFS_SHOW_MAX(RP0_freq_mhz);
406 INTEL_GT_SYSFS_SHOW_MAX(RP1_freq_mhz);
407 INTEL_GT_SYSFS_SHOW_MAX(RPn_freq_mhz);
408 INTEL_GT_SYSFS_SHOW_MAX(max_freq_mhz);
409 INTEL_GT_SYSFS_SHOW_MIN(min_freq_mhz);
410 INTEL_GT_SYSFS_SHOW_MAX(vlv_rpe_freq_mhz);
411 INTEL_GT_SYSFS_STORE(boost_freq_mhz, __boost_freq_mhz_store);
412 INTEL_GT_SYSFS_STORE(max_freq_mhz, __set_max_freq);
413 INTEL_GT_SYSFS_STORE(min_freq_mhz, __set_min_freq);
414 
415 #define INTEL_GT_RPS_SYSFS_ATTR(_name, _mode, _show, _store, _show_dev, _store_dev)		\
416 	static struct device_attribute dev_attr_gt_##_name = __ATTR(gt_##_name, _mode,		\
417 								    _show_dev, _store_dev);	\
418 	static struct kobj_attribute attr_rps_##_name = __ATTR(rps_##_name, _mode,		\
419 							       _show, _store)
420 
421 #define INTEL_GT_RPS_SYSFS_ATTR_RO(_name)						\
422 		INTEL_GT_RPS_SYSFS_ATTR(_name, 0444, _name##_show, NULL,		\
423 					_name##_dev_show, NULL)
424 #define INTEL_GT_RPS_SYSFS_ATTR_RW(_name)						\
425 		INTEL_GT_RPS_SYSFS_ATTR(_name, 0644, _name##_show, _name##_store,	\
426 					_name##_dev_show, _name##_dev_store)
427 
428 /* The below macros generate static structures */
429 INTEL_GT_RPS_SYSFS_ATTR_RO(act_freq_mhz);
430 INTEL_GT_RPS_SYSFS_ATTR_RO(cur_freq_mhz);
431 INTEL_GT_RPS_SYSFS_ATTR_RW(boost_freq_mhz);
432 INTEL_GT_RPS_SYSFS_ATTR_RO(RP0_freq_mhz);
433 INTEL_GT_RPS_SYSFS_ATTR_RO(RP1_freq_mhz);
434 INTEL_GT_RPS_SYSFS_ATTR_RO(RPn_freq_mhz);
435 INTEL_GT_RPS_SYSFS_ATTR_RW(max_freq_mhz);
436 INTEL_GT_RPS_SYSFS_ATTR_RW(min_freq_mhz);
437 INTEL_GT_RPS_SYSFS_ATTR_RO(vlv_rpe_freq_mhz);
438 
439 #define GEN6_ATTR(p, s) { \
440 		&p##attr_##s##_act_freq_mhz.attr, \
441 		&p##attr_##s##_cur_freq_mhz.attr, \
442 		&p##attr_##s##_boost_freq_mhz.attr, \
443 		&p##attr_##s##_max_freq_mhz.attr, \
444 		&p##attr_##s##_min_freq_mhz.attr, \
445 		&p##attr_##s##_RP0_freq_mhz.attr, \
446 		&p##attr_##s##_RP1_freq_mhz.attr, \
447 		&p##attr_##s##_RPn_freq_mhz.attr, \
448 		NULL, \
449 	}
450 
451 #define GEN6_RPS_ATTR GEN6_ATTR(, rps)
452 #define GEN6_GT_ATTR  GEN6_ATTR(dev_, gt)
453 
454 static const struct attribute * const gen6_rps_attrs[] = GEN6_RPS_ATTR;
455 static const struct attribute * const gen6_gt_attrs[]  = GEN6_GT_ATTR;
456 
457 static ssize_t punit_req_freq_mhz_show(struct kobject *kobj,
458 				       struct kobj_attribute *attr,
459 				       char *buff)
460 {
461 	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
462 	u32 preq = intel_rps_read_punit_req_frequency(&gt->rps);
463 
464 	return sysfs_emit(buff, "%u\n", preq);
465 }
466 
467 struct intel_gt_bool_throttle_attr {
468 	struct attribute attr;
469 	ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
470 			char *buf);
471 	i915_reg_t reg32;
472 	u32 mask;
473 };
474 
475 static ssize_t throttle_reason_bool_show(struct kobject *kobj,
476 					 struct kobj_attribute *attr,
477 					 char *buff)
478 {
479 	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
480 	struct intel_gt_bool_throttle_attr *t_attr =
481 				(struct intel_gt_bool_throttle_attr *) attr;
482 	bool val = rps_read_mask_mmio(&gt->rps, t_attr->reg32, t_attr->mask);
483 
484 	return sysfs_emit(buff, "%u\n", val);
485 }
486 
487 #define INTEL_GT_RPS_BOOL_ATTR_RO(sysfs_func__, mask__) \
488 struct intel_gt_bool_throttle_attr attr_##sysfs_func__ = { \
489 	.attr = { .name = __stringify(sysfs_func__), .mode = 0444 }, \
490 	.show = throttle_reason_bool_show, \
491 	.reg32 = GT0_PERF_LIMIT_REASONS, \
492 	.mask = mask__, \
493 }
494 
495 INTEL_GT_ATTR_RO(punit_req_freq_mhz);
496 static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_status, GT0_PERF_LIMIT_REASONS_MASK);
497 static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_pl1, POWER_LIMIT_1_MASK);
498 static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_pl2, POWER_LIMIT_2_MASK);
499 static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_pl4, POWER_LIMIT_4_MASK);
500 static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_thermal, THERMAL_LIMIT_MASK);
501 static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_prochot, PROCHOT_MASK);
502 static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_ratl, RATL_MASK);
503 static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_vr_thermalert, VR_THERMALERT_MASK);
504 static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_vr_tdc, VR_TDC_MASK);
505 
506 static const struct attribute *throttle_reason_attrs[] = {
507 	&attr_throttle_reason_status.attr,
508 	&attr_throttle_reason_pl1.attr,
509 	&attr_throttle_reason_pl2.attr,
510 	&attr_throttle_reason_pl4.attr,
511 	&attr_throttle_reason_thermal.attr,
512 	&attr_throttle_reason_prochot.attr,
513 	&attr_throttle_reason_ratl.attr,
514 	&attr_throttle_reason_vr_thermalert.attr,
515 	&attr_throttle_reason_vr_tdc.attr,
516 	NULL
517 };
518 
519 /*
520  * Scaling for multipliers (aka frequency factors).
521  * The format of the value in the register is u8.8.
522  *
523  * The presentation to userspace is inspired by the perf event framework.
524  * See:
525  *   Documentation/ABI/testing/sysfs-bus-event_source-devices-events
526  * for description of:
527  *   /sys/bus/event_source/devices/<pmu>/events/<event>.scale
528  *
529  * Summary: Expose two sysfs files for each multiplier.
530  *
531  * 1. File <attr> contains a raw hardware value.
532  * 2. File <attr>.scale contains the multiplicative scale factor to be
533  *    used by userspace to compute the actual value.
534  *
535  * So userspace knows that to get the frequency_factor it multiplies the
536  * provided value by the specified scale factor and vice-versa.
537  *
538  * That way there is no precision loss in the kernel interface and API
539  * is future proof should one day the hardware register change to u16.u16,
540  * on some platform. (Or any other fixed point representation.)
541  *
542  * Example:
543  * File <attr> contains the value 2.5, represented as u8.8 0x0280, which
544  * is comprised of:
545  * - an integer part of 2
546  * - a fractional part of 0x80 (representing 0x80 / 2^8 == 0x80 / 256).
547  * File <attr>.scale contains a string representation of floating point
548  * value 0.00390625 (which is (1 / 256)).
549  * Userspace computes the actual value:
550  *   0x0280 * 0.00390625 -> 2.5
551  * or converts an actual value to the value to be written into <attr>:
552  *   2.5 / 0.00390625 -> 0x0280
553  */
554 
555 #define U8_8_VAL_MASK           0xffff
556 #define U8_8_SCALE_TO_VALUE     "0.00390625"
557 
558 static ssize_t freq_factor_scale_show(struct kobject *kobj,
559 				      struct kobj_attribute *attr,
560 				      char *buff)
561 {
562 	return sysfs_emit(buff, "%s\n", U8_8_SCALE_TO_VALUE);
563 }
564 
565 static u32 media_ratio_mode_to_factor(u32 mode)
566 {
567 	/* 0 -> 0, 1 -> 256, 2 -> 128 */
568 	return !mode ? mode : 256 / mode;
569 }
570 
571 static ssize_t media_freq_factor_show(struct kobject *kobj,
572 				      struct kobj_attribute *attr,
573 				      char *buff)
574 {
575 	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
576 	struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
577 	intel_wakeref_t wakeref;
578 	u32 mode;
579 
580 	/*
581 	 * Retrieve media_ratio_mode from GEN6_RPNSWREQ bit 13 set by
582 	 * GuC. GEN6_RPNSWREQ:13 value 0 represents 1:2 and 1 represents 1:1
583 	 */
584 	if (IS_XEHPSDV(gt->i915) &&
585 	    slpc->media_ratio_mode == SLPC_MEDIA_RATIO_MODE_DYNAMIC_CONTROL) {
586 		/*
587 		 * For XEHPSDV dynamic mode GEN6_RPNSWREQ:13 does not contain
588 		 * the media_ratio_mode, just return the cached media ratio
589 		 */
590 		mode = slpc->media_ratio_mode;
591 	} else {
592 		with_intel_runtime_pm(gt->uncore->rpm, wakeref)
593 			mode = intel_uncore_read(gt->uncore, GEN6_RPNSWREQ);
594 		mode = REG_FIELD_GET(GEN12_MEDIA_FREQ_RATIO, mode) ?
595 			SLPC_MEDIA_RATIO_MODE_FIXED_ONE_TO_ONE :
596 			SLPC_MEDIA_RATIO_MODE_FIXED_ONE_TO_TWO;
597 	}
598 
599 	return sysfs_emit(buff, "%u\n", media_ratio_mode_to_factor(mode));
600 }
601 
602 static ssize_t media_freq_factor_store(struct kobject *kobj,
603 				       struct kobj_attribute *attr,
604 				       const char *buff, size_t count)
605 {
606 	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
607 	struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
608 	u32 factor, mode;
609 	int err;
610 
611 	err = kstrtou32(buff, 0, &factor);
612 	if (err)
613 		return err;
614 
615 	for (mode = SLPC_MEDIA_RATIO_MODE_DYNAMIC_CONTROL;
616 	     mode <= SLPC_MEDIA_RATIO_MODE_FIXED_ONE_TO_TWO; mode++)
617 		if (factor == media_ratio_mode_to_factor(mode))
618 			break;
619 
620 	if (mode > SLPC_MEDIA_RATIO_MODE_FIXED_ONE_TO_TWO)
621 		return -EINVAL;
622 
623 	err = intel_guc_slpc_set_media_ratio_mode(slpc, mode);
624 	if (!err) {
625 		slpc->media_ratio_mode = mode;
626 		DRM_DEBUG("Set slpc->media_ratio_mode to %d", mode);
627 	}
628 	return err ?: count;
629 }
630 
631 static ssize_t media_RP0_freq_mhz_show(struct kobject *kobj,
632 				       struct kobj_attribute *attr,
633 				       char *buff)
634 {
635 	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
636 	u32 val;
637 	int err;
638 
639 	err = snb_pcode_read_p(gt->uncore, XEHP_PCODE_FREQUENCY_CONFIG,
640 			       PCODE_MBOX_FC_SC_READ_FUSED_P0,
641 			       PCODE_MBOX_DOMAIN_MEDIAFF, &val);
642 
643 	if (err)
644 		return err;
645 
646 	/* Fused media RP0 read from pcode is in units of 50 MHz */
647 	val *= GT_FREQUENCY_MULTIPLIER;
648 
649 	return sysfs_emit(buff, "%u\n", val);
650 }
651 
652 static ssize_t media_RPn_freq_mhz_show(struct kobject *kobj,
653 				       struct kobj_attribute *attr,
654 				       char *buff)
655 {
656 	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
657 	u32 val;
658 	int err;
659 
660 	err = snb_pcode_read_p(gt->uncore, XEHP_PCODE_FREQUENCY_CONFIG,
661 			       PCODE_MBOX_FC_SC_READ_FUSED_PN,
662 			       PCODE_MBOX_DOMAIN_MEDIAFF, &val);
663 
664 	if (err)
665 		return err;
666 
667 	/* Fused media RPn read from pcode is in units of 50 MHz */
668 	val *= GT_FREQUENCY_MULTIPLIER;
669 
670 	return sysfs_emit(buff, "%u\n", val);
671 }
672 
673 INTEL_GT_ATTR_RW(media_freq_factor);
674 static struct kobj_attribute attr_media_freq_factor_scale =
675 	__ATTR(media_freq_factor.scale, 0444, freq_factor_scale_show, NULL);
676 INTEL_GT_ATTR_RO(media_RP0_freq_mhz);
677 INTEL_GT_ATTR_RO(media_RPn_freq_mhz);
678 
679 static const struct attribute *media_perf_power_attrs[] = {
680 	&attr_media_freq_factor.attr,
681 	&attr_media_freq_factor_scale.attr,
682 	&attr_media_RP0_freq_mhz.attr,
683 	&attr_media_RPn_freq_mhz.attr,
684 	NULL
685 };
686 
687 static ssize_t
688 default_min_freq_mhz_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
689 {
690 	struct intel_gt *gt = kobj_to_gt(kobj->parent);
691 
692 	return sysfs_emit(buf, "%u\n", gt->defaults.min_freq);
693 }
694 
695 static struct kobj_attribute default_min_freq_mhz =
696 __ATTR(rps_min_freq_mhz, 0444, default_min_freq_mhz_show, NULL);
697 
698 static ssize_t
699 default_max_freq_mhz_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
700 {
701 	struct intel_gt *gt = kobj_to_gt(kobj->parent);
702 
703 	return sysfs_emit(buf, "%u\n", gt->defaults.max_freq);
704 }
705 
706 static struct kobj_attribute default_max_freq_mhz =
707 __ATTR(rps_max_freq_mhz, 0444, default_max_freq_mhz_show, NULL);
708 
709 static const struct attribute * const rps_defaults_attrs[] = {
710 	&default_min_freq_mhz.attr,
711 	&default_max_freq_mhz.attr,
712 	NULL
713 };
714 
715 static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj)
716 {
717 	const struct attribute * const *attrs;
718 	struct attribute *vlv_attr;
719 	int ret;
720 
721 	if (GRAPHICS_VER(gt->i915) < 6)
722 		return 0;
723 
724 	if (is_object_gt(kobj)) {
725 		attrs = gen6_rps_attrs;
726 		vlv_attr = &attr_rps_vlv_rpe_freq_mhz.attr;
727 	} else {
728 		attrs = gen6_gt_attrs;
729 		vlv_attr = &dev_attr_gt_vlv_rpe_freq_mhz.attr;
730 	}
731 
732 	ret = sysfs_create_files(kobj, attrs);
733 	if (ret)
734 		return ret;
735 
736 	if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915))
737 		ret = sysfs_create_file(kobj, vlv_attr);
738 
739 	return ret;
740 }
741 
742 #endif /* notyet */
743 
744 void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj)
745 {
746 	STUB();
747 #ifdef notyet
748 	int ret;
749 
750 	intel_sysfs_rc6_init(gt, kobj);
751 
752 	ret = intel_sysfs_rps_init(gt, kobj);
753 	if (ret)
754 		drm_warn(&gt->i915->drm,
755 			 "failed to create gt%u RPS sysfs files (%pe)",
756 			 gt->info.id, ERR_PTR(ret));
757 
758 	/* end of the legacy interfaces */
759 	if (!is_object_gt(kobj))
760 		return;
761 
762 	ret = sysfs_create_file(kobj, &attr_punit_req_freq_mhz.attr);
763 	if (ret)
764 		drm_warn(&gt->i915->drm,
765 			 "failed to create gt%u punit_req_freq_mhz sysfs (%pe)",
766 			 gt->info.id, ERR_PTR(ret));
767 
768 	if (GRAPHICS_VER(gt->i915) >= 11) {
769 		ret = sysfs_create_files(kobj, throttle_reason_attrs);
770 		if (ret)
771 			drm_warn(&gt->i915->drm,
772 				 "failed to create gt%u throttle sysfs files (%pe)",
773 				 gt->info.id, ERR_PTR(ret));
774 	}
775 
776 	if (HAS_MEDIA_RATIO_MODE(gt->i915) && intel_uc_uses_guc_slpc(&gt->uc)) {
777 		ret = sysfs_create_files(kobj, media_perf_power_attrs);
778 		if (ret)
779 			drm_warn(&gt->i915->drm,
780 				 "failed to create gt%u media_perf_power_attrs sysfs (%pe)\n",
781 				 gt->info.id, ERR_PTR(ret));
782 	}
783 
784 	ret = sysfs_create_files(gt->sysfs_defaults, rps_defaults_attrs);
785 	if (ret)
786 		drm_warn(&gt->i915->drm,
787 			 "failed to add gt%u rps defaults (%pe)\n",
788 			 gt->info.id, ERR_PTR(ret));
789 #endif
790 }
791