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