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 	&timeslice_duration_def.attr,
521 	&timeslice_duration_min_def.attr,
522 	&timeslice_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 	&timeslice_duration_attr.attr,
534 	&timeslice_duration_min_attr.attr,
535 	&timeslice_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