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