xref: /linux/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c (revision daa121128a2d2ac6006159e2c47676e4fcd21eab)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #include <drm/drm_managed.h>
7 #include <linux/kobject.h>
8 #include <linux/sysfs.h>
9 
10 #include "xe_device.h"
11 #include "xe_gt.h"
12 #include "xe_hw_engine_class_sysfs.h"
13 #include "xe_pm.h"
14 
15 #define MAX_ENGINE_CLASS_NAME_LEN    16
16 static int xe_add_hw_engine_class_defaults(struct xe_device *xe,
17 					   struct kobject *parent);
18 
19 /**
20  * xe_hw_engine_timeout_in_range - Helper to check if timeout is in range
21  * @timeout: timeout to validate
22  * @min: min value of valid range
23  * @max: max value of valid range
24  *
25  * This helper helps to validate if timeout is in min-max range of HW engine
26  * scheduler.
27  *
28  * Returns: Returns false value for failure and true for success.
29  */
30 bool xe_hw_engine_timeout_in_range(u64 timeout, u64 min, u64 max)
31 {
32 	return timeout >= min && timeout <= max;
33 }
34 
35 static void kobj_xe_hw_engine_release(struct kobject *kobj)
36 {
37 	kfree(kobj);
38 }
39 
40 static const struct kobj_type kobj_xe_hw_engine_type = {
41 	.release = kobj_xe_hw_engine_release,
42 	.sysfs_ops = &kobj_sysfs_ops
43 };
44 
45 static ssize_t job_timeout_max_store(struct kobject *kobj,
46 				     struct kobj_attribute *attr,
47 				     const char *buf, size_t count)
48 {
49 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
50 	u32 timeout;
51 	int err;
52 
53 	err = kstrtou32(buf, 0, &timeout);
54 	if (err)
55 		return err;
56 
57 	if (timeout < eclass->sched_props.job_timeout_min)
58 		return -EINVAL;
59 
60 	if (!xe_hw_engine_timeout_in_range(timeout,
61 					   XE_HW_ENGINE_JOB_TIMEOUT_MIN,
62 					   XE_HW_ENGINE_JOB_TIMEOUT_MAX))
63 		return -EINVAL;
64 
65 	WRITE_ONCE(eclass->sched_props.job_timeout_max, timeout);
66 
67 	return count;
68 }
69 
70 static ssize_t job_timeout_max_show(struct kobject *kobj,
71 				    struct kobj_attribute *attr, char *buf)
72 {
73 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
74 
75 	return sysfs_emit(buf, "%u\n", eclass->sched_props.job_timeout_max);
76 }
77 
78 static const struct kobj_attribute job_timeout_max_attr =
79 __ATTR(job_timeout_max, 0644, job_timeout_max_show, job_timeout_max_store);
80 
81 static ssize_t job_timeout_min_store(struct kobject *kobj,
82 				     struct kobj_attribute *attr,
83 				     const char *buf, size_t count)
84 {
85 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
86 	u32 timeout;
87 	int err;
88 
89 	err = kstrtou32(buf, 0, &timeout);
90 	if (err)
91 		return err;
92 
93 	if (timeout > eclass->sched_props.job_timeout_max)
94 		return -EINVAL;
95 
96 	if (!xe_hw_engine_timeout_in_range(timeout,
97 					   XE_HW_ENGINE_JOB_TIMEOUT_MIN,
98 					   XE_HW_ENGINE_JOB_TIMEOUT_MAX))
99 		return -EINVAL;
100 
101 	WRITE_ONCE(eclass->sched_props.job_timeout_min, timeout);
102 
103 	return count;
104 }
105 
106 static ssize_t job_timeout_min_show(struct kobject *kobj,
107 				    struct kobj_attribute *attr, char *buf)
108 {
109 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
110 
111 	return sysfs_emit(buf, "%u\n", eclass->sched_props.job_timeout_min);
112 }
113 
114 static const struct kobj_attribute job_timeout_min_attr =
115 __ATTR(job_timeout_min, 0644, job_timeout_min_show, job_timeout_min_store);
116 
117 static ssize_t job_timeout_store(struct kobject *kobj,
118 				 struct kobj_attribute *attr,
119 				 const char *buf, size_t count)
120 {
121 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
122 	u32 min = eclass->sched_props.job_timeout_min;
123 	u32 max = eclass->sched_props.job_timeout_max;
124 	u32 timeout;
125 	int err;
126 
127 	err = kstrtou32(buf, 0, &timeout);
128 	if (err)
129 		return err;
130 
131 	if (!xe_hw_engine_timeout_in_range(timeout, min, max))
132 		return -EINVAL;
133 
134 	WRITE_ONCE(eclass->sched_props.job_timeout_ms, timeout);
135 
136 	return count;
137 }
138 
139 static ssize_t job_timeout_show(struct kobject *kobj,
140 				struct kobj_attribute *attr, char *buf)
141 {
142 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
143 
144 	return sysfs_emit(buf, "%u\n", eclass->sched_props.job_timeout_ms);
145 }
146 
147 static const struct kobj_attribute job_timeout_attr =
148 __ATTR(job_timeout_ms, 0644, job_timeout_show, job_timeout_store);
149 
150 static ssize_t job_timeout_default(struct kobject *kobj,
151 				   struct kobj_attribute *attr, char *buf)
152 {
153 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
154 
155 	return sysfs_emit(buf, "%u\n", eclass->defaults.job_timeout_ms);
156 }
157 
158 static const struct kobj_attribute job_timeout_def =
159 __ATTR(job_timeout_ms, 0444, job_timeout_default, NULL);
160 
161 static ssize_t job_timeout_min_default(struct kobject *kobj,
162 				       struct kobj_attribute *attr, char *buf)
163 {
164 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
165 
166 	return sysfs_emit(buf, "%u\n", eclass->defaults.job_timeout_min);
167 }
168 
169 static const struct kobj_attribute job_timeout_min_def =
170 __ATTR(job_timeout_min, 0444, job_timeout_min_default, NULL);
171 
172 static ssize_t job_timeout_max_default(struct kobject *kobj,
173 				       struct kobj_attribute *attr, char *buf)
174 {
175 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
176 
177 	return sysfs_emit(buf, "%u\n", eclass->defaults.job_timeout_max);
178 }
179 
180 static const struct kobj_attribute job_timeout_max_def =
181 __ATTR(job_timeout_max, 0444, job_timeout_max_default, NULL);
182 
183 static ssize_t timeslice_duration_store(struct kobject *kobj,
184 					struct kobj_attribute *attr,
185 					const char *buf, size_t count)
186 {
187 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
188 	u32 min = eclass->sched_props.timeslice_min;
189 	u32 max = eclass->sched_props.timeslice_max;
190 	u32 duration;
191 	int err;
192 
193 	err = kstrtou32(buf, 0, &duration);
194 	if (err)
195 		return err;
196 
197 	if (!xe_hw_engine_timeout_in_range(duration, min, max))
198 		return -EINVAL;
199 
200 	WRITE_ONCE(eclass->sched_props.timeslice_us, duration);
201 
202 	return count;
203 }
204 
205 static ssize_t timeslice_duration_max_store(struct kobject *kobj,
206 					    struct kobj_attribute *attr,
207 					    const char *buf, size_t count)
208 {
209 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
210 	u32 duration;
211 	int err;
212 
213 	err = kstrtou32(buf, 0, &duration);
214 	if (err)
215 		return err;
216 
217 	if (duration < eclass->sched_props.timeslice_min)
218 		return -EINVAL;
219 
220 	if (!xe_hw_engine_timeout_in_range(duration,
221 					   XE_HW_ENGINE_TIMESLICE_MIN,
222 					   XE_HW_ENGINE_TIMESLICE_MAX))
223 		return -EINVAL;
224 
225 	WRITE_ONCE(eclass->sched_props.timeslice_max, duration);
226 
227 	return count;
228 }
229 
230 static ssize_t timeslice_duration_max_show(struct kobject *kobj,
231 					   struct kobj_attribute *attr,
232 					   char *buf)
233 {
234 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
235 
236 	return sysfs_emit(buf, "%u\n", eclass->sched_props.timeslice_max);
237 }
238 
239 static const struct kobj_attribute timeslice_duration_max_attr =
240 	__ATTR(timeslice_duration_max, 0644, timeslice_duration_max_show,
241 	       timeslice_duration_max_store);
242 
243 static ssize_t timeslice_duration_min_store(struct kobject *kobj,
244 					    struct kobj_attribute *attr,
245 					    const char *buf, size_t count)
246 {
247 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
248 	u32 duration;
249 	int err;
250 
251 	err = kstrtou32(buf, 0, &duration);
252 	if (err)
253 		return err;
254 
255 	if (duration > eclass->sched_props.timeslice_max)
256 		return -EINVAL;
257 
258 	if (!xe_hw_engine_timeout_in_range(duration,
259 					   XE_HW_ENGINE_TIMESLICE_MIN,
260 					   XE_HW_ENGINE_TIMESLICE_MAX))
261 		return -EINVAL;
262 
263 	WRITE_ONCE(eclass->sched_props.timeslice_min, duration);
264 
265 	return count;
266 }
267 
268 static ssize_t timeslice_duration_min_show(struct kobject *kobj,
269 					   struct kobj_attribute *attr,
270 					   char *buf)
271 {
272 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
273 
274 	return sysfs_emit(buf, "%u\n", eclass->sched_props.timeslice_min);
275 }
276 
277 static const struct kobj_attribute timeslice_duration_min_attr =
278 	__ATTR(timeslice_duration_min, 0644, timeslice_duration_min_show,
279 	       timeslice_duration_min_store);
280 
281 static ssize_t timeslice_duration_show(struct kobject *kobj,
282 				       struct kobj_attribute *attr, char *buf)
283 {
284 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
285 
286 	return sysfs_emit(buf, "%u\n", eclass->sched_props.timeslice_us);
287 }
288 
289 static const struct kobj_attribute timeslice_duration_attr =
290 	__ATTR(timeslice_duration_us, 0644, timeslice_duration_show,
291 	       timeslice_duration_store);
292 
293 static ssize_t timeslice_default(struct kobject *kobj,
294 				 struct kobj_attribute *attr, char *buf)
295 {
296 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
297 
298 	return sysfs_emit(buf, "%u\n", eclass->defaults.timeslice_us);
299 }
300 
301 static const struct kobj_attribute timeslice_duration_def =
302 __ATTR(timeslice_duration_us, 0444, timeslice_default, NULL);
303 
304 static ssize_t timeslice_min_default(struct kobject *kobj,
305 				     struct kobj_attribute *attr, char *buf)
306 {
307 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
308 
309 	return sysfs_emit(buf, "%u\n", eclass->defaults.timeslice_min);
310 }
311 
312 static const struct kobj_attribute timeslice_duration_min_def =
313 __ATTR(timeslice_duration_min, 0444, timeslice_min_default, NULL);
314 
315 static ssize_t timeslice_max_default(struct kobject *kobj,
316 				     struct kobj_attribute *attr, char *buf)
317 {
318 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
319 
320 	return sysfs_emit(buf, "%u\n", eclass->defaults.timeslice_max);
321 }
322 
323 static const struct kobj_attribute timeslice_duration_max_def =
324 __ATTR(timeslice_duration_max, 0444, timeslice_max_default, NULL);
325 
326 static ssize_t preempt_timeout_store(struct kobject *kobj,
327 				     struct kobj_attribute *attr,
328 				     const char *buf, size_t count)
329 {
330 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
331 	u32 min = eclass->sched_props.preempt_timeout_min;
332 	u32 max = eclass->sched_props.preempt_timeout_max;
333 	u32 timeout;
334 	int err;
335 
336 	err = kstrtou32(buf, 0, &timeout);
337 	if (err)
338 		return err;
339 
340 	if (!xe_hw_engine_timeout_in_range(timeout, min, max))
341 		return -EINVAL;
342 
343 	WRITE_ONCE(eclass->sched_props.preempt_timeout_us, timeout);
344 
345 	return count;
346 }
347 
348 static ssize_t preempt_timeout_show(struct kobject *kobj,
349 				    struct kobj_attribute *attr, char *buf)
350 {
351 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
352 
353 	return sysfs_emit(buf, "%u\n", eclass->sched_props.preempt_timeout_us);
354 }
355 
356 static const struct kobj_attribute preempt_timeout_attr =
357 __ATTR(preempt_timeout_us, 0644, preempt_timeout_show, preempt_timeout_store);
358 
359 static ssize_t preempt_timeout_default(struct kobject *kobj,
360 				       struct kobj_attribute *attr,
361 				       char *buf)
362 {
363 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
364 
365 	return sysfs_emit(buf, "%u\n", eclass->defaults.preempt_timeout_us);
366 }
367 
368 static const struct kobj_attribute preempt_timeout_def =
369 __ATTR(preempt_timeout_us, 0444, preempt_timeout_default, NULL);
370 
371 static ssize_t preempt_timeout_min_default(struct kobject *kobj,
372 					   struct kobj_attribute *attr,
373 					   char *buf)
374 {
375 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
376 
377 	return sysfs_emit(buf, "%u\n", eclass->defaults.preempt_timeout_min);
378 }
379 
380 static const struct kobj_attribute preempt_timeout_min_def =
381 __ATTR(preempt_timeout_min, 0444, preempt_timeout_min_default, NULL);
382 
383 static ssize_t preempt_timeout_max_default(struct kobject *kobj,
384 					   struct kobj_attribute *attr,
385 					   char *buf)
386 {
387 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
388 
389 	return sysfs_emit(buf, "%u\n", eclass->defaults.preempt_timeout_max);
390 }
391 
392 static const struct kobj_attribute preempt_timeout_max_def =
393 __ATTR(preempt_timeout_max, 0444, preempt_timeout_max_default, NULL);
394 
395 static ssize_t preempt_timeout_max_store(struct kobject *kobj,
396 					 struct kobj_attribute *attr,
397 					 const char *buf, size_t count)
398 {
399 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
400 	u32 timeout;
401 	int err;
402 
403 	err = kstrtou32(buf, 0, &timeout);
404 	if (err)
405 		return err;
406 
407 	if (timeout < eclass->sched_props.preempt_timeout_min)
408 		return -EINVAL;
409 
410 	if (!xe_hw_engine_timeout_in_range(timeout,
411 					   XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN,
412 					   XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX))
413 		return -EINVAL;
414 
415 	WRITE_ONCE(eclass->sched_props.preempt_timeout_max, timeout);
416 
417 	return count;
418 }
419 
420 static ssize_t preempt_timeout_max_show(struct kobject *kobj,
421 					struct kobj_attribute *attr, char *buf)
422 {
423 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
424 
425 	return sysfs_emit(buf, "%u\n", eclass->sched_props.preempt_timeout_max);
426 }
427 
428 static const struct kobj_attribute preempt_timeout_max_attr =
429 	__ATTR(preempt_timeout_max, 0644, preempt_timeout_max_show,
430 	       preempt_timeout_max_store);
431 
432 static ssize_t preempt_timeout_min_store(struct kobject *kobj,
433 					 struct kobj_attribute *attr,
434 					 const char *buf, size_t count)
435 {
436 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
437 	u32 timeout;
438 	int err;
439 
440 	err = kstrtou32(buf, 0, &timeout);
441 	if (err)
442 		return err;
443 
444 	if (timeout > eclass->sched_props.preempt_timeout_max)
445 		return -EINVAL;
446 
447 	if (!xe_hw_engine_timeout_in_range(timeout,
448 					   XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN,
449 					   XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX))
450 		return -EINVAL;
451 
452 	WRITE_ONCE(eclass->sched_props.preempt_timeout_min, timeout);
453 
454 	return count;
455 }
456 
457 static ssize_t preempt_timeout_min_show(struct kobject *kobj,
458 					struct kobj_attribute *attr, char *buf)
459 {
460 	struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
461 
462 	return sysfs_emit(buf, "%u\n", eclass->sched_props.preempt_timeout_min);
463 }
464 
465 static const struct kobj_attribute preempt_timeout_min_attr =
466 	__ATTR(preempt_timeout_min, 0644, preempt_timeout_min_show,
467 	       preempt_timeout_min_store);
468 
469 static const struct attribute *defaults[] = {
470 	&job_timeout_def.attr,
471 	&job_timeout_min_def.attr,
472 	&job_timeout_max_def.attr,
473 	&timeslice_duration_def.attr,
474 	&timeslice_duration_min_def.attr,
475 	&timeslice_duration_max_def.attr,
476 	&preempt_timeout_def.attr,
477 	&preempt_timeout_min_def.attr,
478 	&preempt_timeout_max_def.attr,
479 	NULL
480 };
481 
482 static const struct attribute * const files[] = {
483 	&job_timeout_attr.attr,
484 	&job_timeout_min_attr.attr,
485 	&job_timeout_max_attr.attr,
486 	&timeslice_duration_attr.attr,
487 	&timeslice_duration_min_attr.attr,
488 	&timeslice_duration_max_attr.attr,
489 	&preempt_timeout_attr.attr,
490 	&preempt_timeout_min_attr.attr,
491 	&preempt_timeout_max_attr.attr,
492 	NULL
493 };
494 
495 static void kobj_xe_hw_engine_class_fini(struct drm_device *drm, void *arg)
496 {
497 	struct kobject *kobj = arg;
498 
499 	sysfs_remove_files(kobj, files);
500 	kobject_put(kobj);
501 }
502 
503 static struct kobj_eclass *
504 kobj_xe_hw_engine_class(struct xe_device *xe, struct kobject *parent, const char *name)
505 {
506 	struct kobj_eclass *keclass;
507 	int err = 0;
508 
509 	keclass = kzalloc(sizeof(*keclass), GFP_KERNEL);
510 	if (!keclass)
511 		return NULL;
512 
513 	kobject_init(&keclass->base, &kobj_xe_hw_engine_type);
514 	if (kobject_add(&keclass->base, parent, "%s", name)) {
515 		kobject_put(&keclass->base);
516 		return NULL;
517 	}
518 	keclass->xe = xe;
519 
520 	err = drmm_add_action_or_reset(&xe->drm, kobj_xe_hw_engine_class_fini,
521 				       &keclass->base);
522 	if (err)
523 		return NULL;
524 
525 	return keclass;
526 }
527 
528 static void hw_engine_class_defaults_fini(struct drm_device *drm, void *arg)
529 {
530 	struct kobject *kobj = arg;
531 
532 	sysfs_remove_files(kobj, defaults);
533 	kobject_put(kobj);
534 }
535 
536 static int xe_add_hw_engine_class_defaults(struct xe_device *xe,
537 					   struct kobject *parent)
538 {
539 	struct kobject *kobj;
540 	int err = 0;
541 
542 	kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
543 	if (!kobj)
544 		return -ENOMEM;
545 
546 	kobject_init(kobj, &kobj_xe_hw_engine_type);
547 	err = kobject_add(kobj, parent, "%s", ".defaults");
548 	if (err)
549 		goto err_object;
550 
551 	err = sysfs_create_files(kobj, defaults);
552 	if (err)
553 		goto err_object;
554 
555 	return drmm_add_action_or_reset(&xe->drm, hw_engine_class_defaults_fini, kobj);
556 
557 err_object:
558 	kobject_put(kobj);
559 	return err;
560 }
561 
562 static void xe_hw_engine_sysfs_kobj_release(struct kobject *kobj)
563 {
564 	kfree(kobj);
565 }
566 
567 static ssize_t xe_hw_engine_class_sysfs_attr_show(struct kobject *kobj,
568 						  struct attribute *attr,
569 						  char *buf)
570 {
571 	struct xe_device *xe = kobj_to_xe(kobj);
572 	struct kobj_attribute *kattr;
573 	ssize_t ret = -EIO;
574 
575 	kattr = container_of(attr, struct kobj_attribute, attr);
576 	if (kattr->show) {
577 		xe_pm_runtime_get(xe);
578 		ret = kattr->show(kobj, kattr, buf);
579 		xe_pm_runtime_put(xe);
580 	}
581 
582 	return ret;
583 }
584 
585 static ssize_t xe_hw_engine_class_sysfs_attr_store(struct kobject *kobj,
586 						   struct attribute *attr,
587 						   const char *buf,
588 						   size_t count)
589 {
590 	struct xe_device *xe = kobj_to_xe(kobj);
591 	struct kobj_attribute *kattr;
592 	ssize_t ret = -EIO;
593 
594 	kattr = container_of(attr, struct kobj_attribute, attr);
595 	if (kattr->store) {
596 		xe_pm_runtime_get(xe);
597 		ret = kattr->store(kobj, kattr, buf, count);
598 		xe_pm_runtime_put(xe);
599 	}
600 
601 	return ret;
602 }
603 
604 static const struct sysfs_ops xe_hw_engine_class_sysfs_ops = {
605 	.show = xe_hw_engine_class_sysfs_attr_show,
606 	.store = xe_hw_engine_class_sysfs_attr_store,
607 };
608 
609 static const struct kobj_type xe_hw_engine_sysfs_kobj_type = {
610 	.release = xe_hw_engine_sysfs_kobj_release,
611 	.sysfs_ops = &xe_hw_engine_class_sysfs_ops,
612 };
613 
614 static void hw_engine_class_sysfs_fini(struct drm_device *drm, void *arg)
615 {
616 	struct kobject *kobj = arg;
617 
618 	kobject_put(kobj);
619 }
620 
621 static const char *xe_hw_engine_class_to_str(enum xe_engine_class class)
622 {
623 	switch (class) {
624 	case XE_ENGINE_CLASS_RENDER:
625 		return "rcs";
626 	case XE_ENGINE_CLASS_VIDEO_DECODE:
627 		return "vcs";
628 	case XE_ENGINE_CLASS_VIDEO_ENHANCE:
629 		return "vecs";
630 	case XE_ENGINE_CLASS_COPY:
631 		return "bcs";
632 	case XE_ENGINE_CLASS_COMPUTE:
633 		return "ccs";
634 	default:
635 		return NULL;
636 	}
637 }
638 
639 /**
640  * xe_hw_engine_class_sysfs_init - Init HW engine classes on GT.
641  * @gt: Xe GT.
642  *
643  * This routine creates sysfs for HW engine classes and adds methods
644  * to get/set different scheduling properties for HW engines class.
645  *
646  * Returns: Returns error value for failure and 0 for success.
647  */
648 int xe_hw_engine_class_sysfs_init(struct xe_gt *gt)
649 {
650 	struct xe_device *xe = gt_to_xe(gt);
651 	struct xe_hw_engine *hwe;
652 	enum xe_hw_engine_id id;
653 	struct kobject *kobj;
654 	u16 class_mask = 0;
655 	int err = 0;
656 
657 	kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
658 	if (!kobj)
659 		return -ENOMEM;
660 
661 	kobject_init(kobj, &xe_hw_engine_sysfs_kobj_type);
662 
663 	err = kobject_add(kobj, gt->sysfs, "engines");
664 	if (err)
665 		goto err_object;
666 
667 	for_each_hw_engine(hwe, gt, id) {
668 		const char *name;
669 		struct kobj_eclass *keclass;
670 
671 		if (hwe->class == XE_ENGINE_CLASS_OTHER ||
672 		    hwe->class == XE_ENGINE_CLASS_MAX)
673 			continue;
674 
675 		if ((class_mask >> hwe->class) & 1)
676 			continue;
677 
678 		class_mask |= 1 << hwe->class;
679 		name = xe_hw_engine_class_to_str(hwe->class);
680 		if (!name) {
681 			err = -EINVAL;
682 			goto err_object;
683 		}
684 
685 		keclass = kobj_xe_hw_engine_class(xe, kobj, name);
686 		if (!keclass) {
687 			err = -EINVAL;
688 			goto err_object;
689 		}
690 
691 		keclass->eclass = hwe->eclass;
692 		err = xe_add_hw_engine_class_defaults(xe, &keclass->base);
693 		if (err)
694 			goto err_object;
695 
696 		err = sysfs_create_files(&keclass->base, files);
697 		if (err)
698 			goto err_object;
699 	}
700 
701 	return drmm_add_action_or_reset(&xe->drm, hw_engine_class_sysfs_fini, kobj);
702 
703 err_object:
704 	kobject_put(kobj);
705 	return err;
706 }
707