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