1 // SPDX-License-Identifier: MIT
3 * Copyright © 2023 Intel Corporation
6 #include <drm/drm_managed.h>
7 #include <linux/kobject.h>
8 #include <linux/sysfs.h>
11 #include "xe_hw_engine_class_sysfs.h"
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);
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
23 * This helper helps to validate if timeout is in min-max range of HW engine
26 * Returns: Returns false value for failure and true for success.
28 bool xe_hw_engine_timeout_in_range(u64 timeout, u64 min, u64 max)
30 return timeout >= min && timeout <= max;
33 static void kobj_xe_hw_engine_release(struct kobject *kobj)
38 static const struct kobj_type kobj_xe_hw_engine_type = {
39 .release = kobj_xe_hw_engine_release,
40 .sysfs_ops = &kobj_sysfs_ops
43 static ssize_t job_timeout_max_store(struct kobject *kobj,
44 struct kobj_attribute *attr,
45 const char *buf, size_t count)
47 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
51 err = kstrtou32(buf, 0, &timeout);
55 if (timeout < eclass->sched_props.job_timeout_min)
58 if (!xe_hw_engine_timeout_in_range(timeout,
59 XE_HW_ENGINE_JOB_TIMEOUT_MIN,
60 XE_HW_ENGINE_JOB_TIMEOUT_MAX))
63 WRITE_ONCE(eclass->sched_props.job_timeout_max, timeout);
68 static ssize_t job_timeout_max_show(struct kobject *kobj,
69 struct kobj_attribute *attr, char *buf)
71 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
73 return sprintf(buf, "%u\n", eclass->sched_props.job_timeout_max);
76 static struct kobj_attribute job_timeout_max_attr =
77 __ATTR(job_timeout_max, 0644, job_timeout_max_show, job_timeout_max_store);
79 static ssize_t job_timeout_min_store(struct kobject *kobj,
80 struct kobj_attribute *attr,
81 const char *buf, size_t count)
83 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
87 err = kstrtou32(buf, 0, &timeout);
91 if (timeout > eclass->sched_props.job_timeout_max)
94 if (!xe_hw_engine_timeout_in_range(timeout,
95 XE_HW_ENGINE_JOB_TIMEOUT_MIN,
96 XE_HW_ENGINE_JOB_TIMEOUT_MAX))
99 WRITE_ONCE(eclass->sched_props.job_timeout_min, timeout);
104 static ssize_t job_timeout_min_show(struct kobject *kobj,
105 struct kobj_attribute *attr, char *buf)
107 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
109 return sprintf(buf, "%u\n", eclass->sched_props.job_timeout_min);
112 static struct kobj_attribute job_timeout_min_attr =
113 __ATTR(job_timeout_min, 0644, job_timeout_min_show, job_timeout_min_store);
115 static ssize_t job_timeout_store(struct kobject *kobj,
116 struct kobj_attribute *attr,
117 const char *buf, size_t count)
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;
125 err = kstrtou32(buf, 0, &timeout);
129 if (!xe_hw_engine_timeout_in_range(timeout, min, max))
132 WRITE_ONCE(eclass->sched_props.job_timeout_ms, timeout);
137 static ssize_t job_timeout_show(struct kobject *kobj,
138 struct kobj_attribute *attr, char *buf)
140 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
142 return sprintf(buf, "%u\n", eclass->sched_props.job_timeout_ms);
145 static struct kobj_attribute job_timeout_attr =
146 __ATTR(job_timeout_ms, 0644, job_timeout_show, job_timeout_store);
148 static ssize_t job_timeout_default(struct kobject *kobj,
149 struct kobj_attribute *attr, char *buf)
151 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
153 return sprintf(buf, "%u\n", eclass->defaults.job_timeout_ms);
156 static struct kobj_attribute job_timeout_def =
157 __ATTR(job_timeout_ms, 0444, job_timeout_default, NULL);
159 static ssize_t job_timeout_min_default(struct kobject *kobj,
160 struct kobj_attribute *attr, char *buf)
162 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
164 return sprintf(buf, "%u\n", eclass->defaults.job_timeout_min);
167 static struct kobj_attribute job_timeout_min_def =
168 __ATTR(job_timeout_min, 0444, job_timeout_min_default, NULL);
170 static ssize_t job_timeout_max_default(struct kobject *kobj,
171 struct kobj_attribute *attr, char *buf)
173 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
175 return sprintf(buf, "%u\n", eclass->defaults.job_timeout_max);
178 static struct kobj_attribute job_timeout_max_def =
179 __ATTR(job_timeout_max, 0444, job_timeout_max_default, NULL);
181 static ssize_t timeslice_duration_store(struct kobject *kobj,
182 struct kobj_attribute *attr,
183 const char *buf, size_t count)
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;
191 err = kstrtou32(buf, 0, &duration);
195 if (!xe_hw_engine_timeout_in_range(duration, min, max))
198 WRITE_ONCE(eclass->sched_props.timeslice_us, duration);
203 static ssize_t timeslice_duration_max_store(struct kobject *kobj,
204 struct kobj_attribute *attr,
205 const char *buf, size_t count)
207 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
211 err = kstrtou32(buf, 0, &duration);
215 if (duration < eclass->sched_props.timeslice_min)
218 if (!xe_hw_engine_timeout_in_range(duration,
219 XE_HW_ENGINE_TIMESLICE_MIN,
220 XE_HW_ENGINE_TIMESLICE_MAX))
223 WRITE_ONCE(eclass->sched_props.timeslice_max, duration);
228 static ssize_t timeslice_duration_max_show(struct kobject *kobj,
229 struct kobj_attribute *attr,
232 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
234 return sprintf(buf, "%u\n", eclass->sched_props.timeslice_max);
237 static struct kobj_attribute timeslice_duration_max_attr =
238 __ATTR(timeslice_duration_max, 0644, timeslice_duration_max_show,
239 timeslice_duration_max_store);
241 static ssize_t timeslice_duration_min_store(struct kobject *kobj,
242 struct kobj_attribute *attr,
243 const char *buf, size_t count)
245 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
249 err = kstrtou32(buf, 0, &duration);
253 if (duration > eclass->sched_props.timeslice_max)
256 if (!xe_hw_engine_timeout_in_range(duration,
257 XE_HW_ENGINE_TIMESLICE_MIN,
258 XE_HW_ENGINE_TIMESLICE_MAX))
261 WRITE_ONCE(eclass->sched_props.timeslice_min, duration);
266 static ssize_t timeslice_duration_min_show(struct kobject *kobj,
267 struct kobj_attribute *attr,
270 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
272 return sprintf(buf, "%u\n", eclass->sched_props.timeslice_min);
275 static struct kobj_attribute timeslice_duration_min_attr =
276 __ATTR(timeslice_duration_min, 0644, timeslice_duration_min_show,
277 timeslice_duration_min_store);
279 static ssize_t timeslice_duration_show(struct kobject *kobj,
280 struct kobj_attribute *attr, char *buf)
282 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
284 return sprintf(buf, "%u\n", eclass->sched_props.timeslice_us);
287 static struct kobj_attribute timeslice_duration_attr =
288 __ATTR(timeslice_duration_us, 0644, timeslice_duration_show,
289 timeslice_duration_store);
291 static ssize_t timeslice_default(struct kobject *kobj,
292 struct kobj_attribute *attr, char *buf)
294 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
296 return sprintf(buf, "%u\n", eclass->defaults.timeslice_us);
299 static struct kobj_attribute timeslice_duration_def =
300 __ATTR(timeslice_duration_us, 0444, timeslice_default, NULL);
302 static ssize_t timeslice_min_default(struct kobject *kobj,
303 struct kobj_attribute *attr, char *buf)
305 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
307 return sprintf(buf, "%u\n", eclass->defaults.timeslice_min);
310 static struct kobj_attribute timeslice_duration_min_def =
311 __ATTR(timeslice_duration_min, 0444, timeslice_min_default, NULL);
313 static ssize_t timeslice_max_default(struct kobject *kobj,
314 struct kobj_attribute *attr, char *buf)
316 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
318 return sprintf(buf, "%u\n", eclass->defaults.timeslice_max);
321 static struct kobj_attribute timeslice_duration_max_def =
322 __ATTR(timeslice_duration_max, 0444, timeslice_max_default, NULL);
324 static ssize_t preempt_timeout_store(struct kobject *kobj,
325 struct kobj_attribute *attr,
326 const char *buf, size_t count)
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;
334 err = kstrtou32(buf, 0, &timeout);
338 if (!xe_hw_engine_timeout_in_range(timeout, min, max))
341 WRITE_ONCE(eclass->sched_props.preempt_timeout_us, timeout);
346 static ssize_t preempt_timeout_show(struct kobject *kobj,
347 struct kobj_attribute *attr, char *buf)
349 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
351 return sprintf(buf, "%u\n", eclass->sched_props.preempt_timeout_us);
354 static struct kobj_attribute preempt_timeout_attr =
355 __ATTR(preempt_timeout_us, 0644, preempt_timeout_show, preempt_timeout_store);
357 static ssize_t preempt_timeout_default(struct kobject *kobj,
358 struct kobj_attribute *attr,
361 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
363 return sprintf(buf, "%u\n", eclass->defaults.preempt_timeout_us);
366 static struct kobj_attribute preempt_timeout_def =
367 __ATTR(preempt_timeout_us, 0444, preempt_timeout_default, NULL);
369 static ssize_t preempt_timeout_min_default(struct kobject *kobj,
370 struct kobj_attribute *attr,
373 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
375 return sprintf(buf, "%u\n", eclass->defaults.preempt_timeout_min);
378 static struct kobj_attribute preempt_timeout_min_def =
379 __ATTR(preempt_timeout_min, 0444, preempt_timeout_min_default, NULL);
381 static ssize_t preempt_timeout_max_default(struct kobject *kobj,
382 struct kobj_attribute *attr,
385 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
387 return sprintf(buf, "%u\n", eclass->defaults.preempt_timeout_max);
390 static struct kobj_attribute preempt_timeout_max_def =
391 __ATTR(preempt_timeout_max, 0444, preempt_timeout_max_default, NULL);
393 static ssize_t preempt_timeout_max_store(struct kobject *kobj,
394 struct kobj_attribute *attr,
395 const char *buf, size_t count)
397 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
401 err = kstrtou32(buf, 0, &timeout);
405 if (timeout < eclass->sched_props.preempt_timeout_min)
408 if (!xe_hw_engine_timeout_in_range(timeout,
409 XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN,
410 XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX))
413 WRITE_ONCE(eclass->sched_props.preempt_timeout_max, timeout);
418 static ssize_t preempt_timeout_max_show(struct kobject *kobj,
419 struct kobj_attribute *attr, char *buf)
421 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
423 return sprintf(buf, "%u\n", eclass->sched_props.preempt_timeout_max);
426 static struct kobj_attribute preempt_timeout_max_attr =
427 __ATTR(preempt_timeout_max, 0644, preempt_timeout_max_show,
428 preempt_timeout_max_store);
430 static ssize_t preempt_timeout_min_store(struct kobject *kobj,
431 struct kobj_attribute *attr,
432 const char *buf, size_t count)
434 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
438 err = kstrtou32(buf, 0, &timeout);
442 if (timeout > eclass->sched_props.preempt_timeout_max)
445 if (!xe_hw_engine_timeout_in_range(timeout,
446 XE_HW_ENGINE_PREEMPT_TIMEOUT_MIN,
447 XE_HW_ENGINE_PREEMPT_TIMEOUT_MAX))
450 WRITE_ONCE(eclass->sched_props.preempt_timeout_min, timeout);
455 static ssize_t preempt_timeout_min_show(struct kobject *kobj,
456 struct kobj_attribute *attr, char *buf)
458 struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj);
460 return sprintf(buf, "%u\n", eclass->sched_props.preempt_timeout_min);
463 static struct kobj_attribute preempt_timeout_min_attr =
464 __ATTR(preempt_timeout_min, 0644, preempt_timeout_min_show,
465 preempt_timeout_min_store);
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,
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,
493 static void kobj_xe_hw_engine_class_fini(struct drm_device *drm, void *arg)
495 struct kobject *kobj = arg;
497 sysfs_remove_files(kobj, files);
501 static struct kobj_eclass *
502 kobj_xe_hw_engine_class(struct xe_device *xe, struct kobject *parent, char *name)
504 struct kobj_eclass *keclass;
507 keclass = kzalloc(sizeof(*keclass), GFP_KERNEL);
511 kobject_init(&keclass->base, &kobj_xe_hw_engine_type);
512 if (kobject_add(&keclass->base, parent, "%s", name)) {
513 kobject_put(&keclass->base);
517 err = drmm_add_action_or_reset(&xe->drm, kobj_xe_hw_engine_class_fini,
521 "%s: drmm_add_action_or_reset failed, err: %d\n",
526 static void hw_engine_class_defaults_fini(struct drm_device *drm, void *arg)
528 struct kobject *kobj = arg;
530 sysfs_remove_files(kobj, defaults);
534 static int xe_add_hw_engine_class_defaults(struct xe_device *xe,
535 struct kobject *parent)
537 struct kobject *kobj;
540 kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
544 kobject_init(kobj, &kobj_xe_hw_engine_type);
545 err = kobject_add(kobj, parent, "%s", ".defaults");
549 err = sysfs_create_files(kobj, defaults);
553 err = drmm_add_action_or_reset(&xe->drm, hw_engine_class_defaults_fini,
557 "%s: drmm_add_action_or_reset failed, err: %d\n",
565 static void xe_hw_engine_sysfs_kobj_release(struct kobject *kobj)
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,
575 static void hw_engine_class_sysfs_fini(struct drm_device *drm, void *arg)
577 struct kobject *kobj = arg;
583 * xe_hw_engine_class_sysfs_init - Init HW engine classes on GT.
586 * This routine creates sysfs for HW engine classes and adds methods
587 * to get/set different scheduling properties for HW engines class.
589 * Returns: Returns error value for failure and 0 for success.
591 int xe_hw_engine_class_sysfs_init(struct xe_gt *gt)
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;
600 kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
604 kobject_init(kobj, &xe_hw_engine_sysfs_kobj_type);
606 err = kobject_add(kobj, gt->sysfs, "engines");
610 for_each_hw_engine(hwe, gt, id) {
611 char name[MAX_ENGINE_CLASS_NAME_LEN];
612 struct kobj_eclass *keclass;
614 if (hwe->class == XE_ENGINE_CLASS_OTHER ||
615 hwe->class == XE_ENGINE_CLASS_MAX)
618 if ((class_mask >> hwe->class) & 1)
621 class_mask |= 1 << hwe->class;
623 switch (hwe->class) {
624 case XE_ENGINE_CLASS_RENDER:
627 case XE_ENGINE_CLASS_VIDEO_DECODE:
630 case XE_ENGINE_CLASS_VIDEO_ENHANCE:
631 strcpy(name, "vecs");
633 case XE_ENGINE_CLASS_COPY:
636 case XE_ENGINE_CLASS_COMPUTE:
644 keclass = kobj_xe_hw_engine_class(xe, kobj, name);
650 keclass->eclass = hwe->eclass;
651 err = xe_add_hw_engine_class_defaults(xe, &keclass->base);
654 "Add .defaults to engines failed!, err: %d\n",
659 err = sysfs_create_files(&keclass->base, files);
664 err = drmm_add_action_or_reset(&xe->drm, hw_engine_class_sysfs_fini,
668 "%s: drmm_add_action_or_reset failed, err: %d\n",