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
kobj_xe_hw_engine_release(struct kobject * kobj)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
job_timeout_max_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)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
job_timeout_max_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
job_timeout_min_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)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
job_timeout_min_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
job_timeout_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)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
job_timeout_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
job_timeout_default(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
job_timeout_min_default(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
job_timeout_max_default(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
timeslice_duration_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)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
timeslice_duration_max_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)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
timeslice_duration_max_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
timeslice_duration_min_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)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
timeslice_duration_min_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
timeslice_duration_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
timeslice_default(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
timeslice_min_default(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
timeslice_max_default(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
preempt_timeout_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)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
preempt_timeout_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
preempt_timeout_default(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
preempt_timeout_min_default(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
preempt_timeout_max_default(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
preempt_timeout_max_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)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
preempt_timeout_max_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
preempt_timeout_min_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)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
preempt_timeout_min_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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 ×lice_duration_def.attr,
474 ×lice_duration_min_def.attr,
475 ×lice_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 ×lice_duration_attr.attr,
487 ×lice_duration_min_attr.attr,
488 ×lice_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
kobj_xe_hw_engine_class_fini(void * arg)495 static void kobj_xe_hw_engine_class_fini(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 *
kobj_xe_hw_engine_class(struct xe_device * xe,struct kobject * parent,const char * name)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 = devm_add_action_or_reset(xe->drm.dev, kobj_xe_hw_engine_class_fini,
521 &keclass->base);
522 if (err)
523 return NULL;
524
525 return keclass;
526 }
527
hw_engine_class_defaults_fini(void * arg)528 static void hw_engine_class_defaults_fini(void *arg)
529 {
530 struct kobject *kobj = arg;
531
532 sysfs_remove_files(kobj, defaults);
533 kobject_put(kobj);
534 }
535
xe_add_hw_engine_class_defaults(struct xe_device * xe,struct kobject * parent)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 devm_add_action_or_reset(xe->drm.dev, hw_engine_class_defaults_fini, kobj);
556
557 err_object:
558 kobject_put(kobj);
559 return err;
560 }
561
xe_hw_engine_sysfs_kobj_release(struct kobject * kobj)562 static void xe_hw_engine_sysfs_kobj_release(struct kobject *kobj)
563 {
564 kfree(kobj);
565 }
566
xe_hw_engine_class_sysfs_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)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
xe_hw_engine_class_sysfs_attr_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t count)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
hw_engine_class_sysfs_fini(void * arg)614 static void hw_engine_class_sysfs_fini(void *arg)
615 {
616 struct kobject *kobj = arg;
617
618 kobject_put(kobj);
619 }
620
621 /**
622 * xe_hw_engine_class_sysfs_init - Init HW engine classes on GT.
623 * @gt: Xe GT.
624 *
625 * This routine creates sysfs for HW engine classes and adds methods
626 * to get/set different scheduling properties for HW engines class.
627 *
628 * Returns: Returns error value for failure and 0 for success.
629 */
xe_hw_engine_class_sysfs_init(struct xe_gt * gt)630 int xe_hw_engine_class_sysfs_init(struct xe_gt *gt)
631 {
632 struct xe_device *xe = gt_to_xe(gt);
633 struct xe_hw_engine *hwe;
634 enum xe_hw_engine_id id;
635 struct kobject *kobj;
636 u16 class_mask = 0;
637 int err = 0;
638
639 kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
640 if (!kobj)
641 return -ENOMEM;
642
643 kobject_init(kobj, &xe_hw_engine_sysfs_kobj_type);
644
645 err = kobject_add(kobj, gt->sysfs, "engines");
646 if (err)
647 goto err_object;
648
649 for_each_hw_engine(hwe, gt, id) {
650 const char *name;
651 struct kobj_eclass *keclass;
652
653 if (hwe->class == XE_ENGINE_CLASS_OTHER ||
654 hwe->class == XE_ENGINE_CLASS_MAX)
655 continue;
656
657 if ((class_mask >> hwe->class) & 1)
658 continue;
659
660 class_mask |= 1 << hwe->class;
661 name = xe_hw_engine_class_to_str(hwe->class);
662 if (!name) {
663 err = -EINVAL;
664 goto err_object;
665 }
666
667 keclass = kobj_xe_hw_engine_class(xe, kobj, name);
668 if (!keclass) {
669 err = -EINVAL;
670 goto err_object;
671 }
672
673 keclass->eclass = hwe->eclass;
674 err = xe_add_hw_engine_class_defaults(xe, &keclass->base);
675 if (err)
676 goto err_object;
677
678 err = sysfs_create_files(&keclass->base, files);
679 if (err)
680 goto err_object;
681 }
682
683 return devm_add_action_or_reset(xe->drm.dev, hw_engine_class_sysfs_fini, kobj);
684
685 err_object:
686 kobject_put(kobj);
687 return err;
688 }
689