brintos

brintos / linux-shallow public Read only

0
0
Text · 17.8 KiB · b53e8d2 Raw
689 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2023 Intel Corporation4 */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    1616static 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 range21 * @timeout: timeout to validate22 * @min: min value of valid range23 * @max: max value of valid range24 *25 * This helper helps to validate if timeout is in min-max range of HW engine26 * scheduler.27 *28 * Returns: Returns false value for failure and true for success.29 */30bool xe_hw_engine_timeout_in_range(u64 timeout, u64 min, u64 max)31{32	return timeout >= min && timeout <= max;33}34 35static void kobj_xe_hw_engine_release(struct kobject *kobj)36{37	kfree(kobj);38}39 40static const struct kobj_type kobj_xe_hw_engine_type = {41	.release = kobj_xe_hw_engine_release,42	.sysfs_ops = &kobj_sysfs_ops43};44 45static 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 70static 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 78static const struct kobj_attribute job_timeout_max_attr =79__ATTR(job_timeout_max, 0644, job_timeout_max_show, job_timeout_max_store);80 81static 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 106static 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 114static const struct kobj_attribute job_timeout_min_attr =115__ATTR(job_timeout_min, 0644, job_timeout_min_show, job_timeout_min_store);116 117static 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 139static 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 147static const struct kobj_attribute job_timeout_attr =148__ATTR(job_timeout_ms, 0644, job_timeout_show, job_timeout_store);149 150static 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 158static const struct kobj_attribute job_timeout_def =159__ATTR(job_timeout_ms, 0444, job_timeout_default, NULL);160 161static 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 169static const struct kobj_attribute job_timeout_min_def =170__ATTR(job_timeout_min, 0444, job_timeout_min_default, NULL);171 172static 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 180static const struct kobj_attribute job_timeout_max_def =181__ATTR(job_timeout_max, 0444, job_timeout_max_default, NULL);182 183static 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 205static 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 230static 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 239static const struct kobj_attribute timeslice_duration_max_attr =240	__ATTR(timeslice_duration_max, 0644, timeslice_duration_max_show,241	       timeslice_duration_max_store);242 243static 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 268static 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 277static const struct kobj_attribute timeslice_duration_min_attr =278	__ATTR(timeslice_duration_min, 0644, timeslice_duration_min_show,279	       timeslice_duration_min_store);280 281static 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 289static const struct kobj_attribute timeslice_duration_attr =290	__ATTR(timeslice_duration_us, 0644, timeslice_duration_show,291	       timeslice_duration_store);292 293static 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 301static const struct kobj_attribute timeslice_duration_def =302__ATTR(timeslice_duration_us, 0444, timeslice_default, NULL);303 304static 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 312static const struct kobj_attribute timeslice_duration_min_def =313__ATTR(timeslice_duration_min, 0444, timeslice_min_default, NULL);314 315static 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 323static const struct kobj_attribute timeslice_duration_max_def =324__ATTR(timeslice_duration_max, 0444, timeslice_max_default, NULL);325 326static 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 348static 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 356static const struct kobj_attribute preempt_timeout_attr =357__ATTR(preempt_timeout_us, 0644, preempt_timeout_show, preempt_timeout_store);358 359static 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 368static const struct kobj_attribute preempt_timeout_def =369__ATTR(preempt_timeout_us, 0444, preempt_timeout_default, NULL);370 371static 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 380static const struct kobj_attribute preempt_timeout_min_def =381__ATTR(preempt_timeout_min, 0444, preempt_timeout_min_default, NULL);382 383static 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 392static const struct kobj_attribute preempt_timeout_max_def =393__ATTR(preempt_timeout_max, 0444, preempt_timeout_max_default, NULL);394 395static 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 420static 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 428static const struct kobj_attribute preempt_timeout_max_attr =429	__ATTR(preempt_timeout_max, 0644, preempt_timeout_max_show,430	       preempt_timeout_max_store);431 432static 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 457static 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 465static const struct kobj_attribute preempt_timeout_min_attr =466	__ATTR(preempt_timeout_min, 0644, preempt_timeout_min_show,467	       preempt_timeout_min_store);468 469static const struct attribute *defaults[] = {470	&job_timeout_def.attr,471	&job_timeout_min_def.attr,472	&job_timeout_max_def.attr,473	&timeslice_duration_def.attr,474	&timeslice_duration_min_def.attr,475	&timeslice_duration_max_def.attr,476	&preempt_timeout_def.attr,477	&preempt_timeout_min_def.attr,478	&preempt_timeout_max_def.attr,479	NULL480};481 482static const struct attribute * const files[] = {483	&job_timeout_attr.attr,484	&job_timeout_min_attr.attr,485	&job_timeout_max_attr.attr,486	&timeslice_duration_attr.attr,487	&timeslice_duration_min_attr.attr,488	&timeslice_duration_max_attr.attr,489	&preempt_timeout_attr.attr,490	&preempt_timeout_min_attr.attr,491	&preempt_timeout_max_attr.attr,492	NULL493};494 495static 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 503static struct kobj_eclass *504kobj_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 528static 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 536static 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 557err_object:558	kobject_put(kobj);559	return err;560}561 562static void xe_hw_engine_sysfs_kobj_release(struct kobject *kobj)563{564	kfree(kobj);565}566 567static 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 585static 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 604static 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 609static 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 614static 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 methods626 * to get/set different scheduling properties for HW engines class.627 *628 * Returns: Returns error value for failure and 0 for success.629 */630int 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 685err_object:686	kobject_put(kobj);687	return err;688}689