#include "xe_hw_engine_class_sysfs.h"
#define MAX_ENGINE_CLASS_NAME_LEN 16
+static int xe_add_hw_engine_class_defaults(struct xe_device *xe,
+ struct kobject *parent);
+
static void kobj_xe_hw_engine_release(struct kobject *kobj)
{
kfree(kobj);
.sysfs_ops = &kobj_sysfs_ops
};
-static void kobj_xe_hw_engine_fini(struct drm_device *drm, void *arg)
+static void kobj_xe_hw_engine_class_fini(struct drm_device *drm, void *arg)
{
struct kobject *kobj = arg;
kobject_put(kobj);
}
- static struct kobject *
-kobj_xe_hw_engine(struct xe_device *xe, struct kobject *parent, char *name)
+ static struct kobj_eclass *
+kobj_xe_hw_engine_class(struct xe_device *xe, struct kobject *parent, char *name)
+{
+ struct kobj_eclass *keclass;
+ int err = 0;
+
+ keclass = kzalloc(sizeof(*keclass), GFP_KERNEL);
+ if (!keclass)
+ return NULL;
+
+ kobject_init(&keclass->base, &kobj_xe_hw_engine_type);
+ if (kobject_add(&keclass->base, parent, "%s", name)) {
+ kobject_put(&keclass->base);
+ return NULL;
+ }
+
+ err = drmm_add_action_or_reset(&xe->drm, kobj_xe_hw_engine_class_fini,
+ &keclass->base);
+ if (err)
+ drm_warn(&xe->drm,
+ "%s: drmm_add_action_or_reset failed, err: %d\n",
+ __func__, err);
+ return keclass;
+}
+
+static ssize_t job_timeout_default(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
+
+ return sprintf(buf, "%u\n", eclass->defaults.job_timeout_ms);
+}
+
+static struct kobj_attribute job_timeout_def =
+__ATTR(job_timeout_ms, 0444, job_timeout_default, NULL);
+
+static ssize_t timeslice_default(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
+
+ return sprintf(buf, "%u\n", eclass->defaults.timeslice_us);
+}
+
+static struct kobj_attribute timeslice_duration_def =
+__ATTR(timeslice_duration_us, 0444, timeslice_default, NULL);
+
+static ssize_t preempt_timeout_default(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ struct xe_hw_engine_class_intf *eclass = kobj_to_eclass(kobj->parent);
+
+ return sprintf(buf, "%u\n", eclass->defaults.preempt_timeout_us);
+}
+
+static struct kobj_attribute preempt_timeout_def =
+__ATTR(preempt_timeout_us, 0444, preempt_timeout_default, NULL);
+
+static const struct attribute *defaults[] = {
+ &job_timeout_def.attr,
+ ×lice_duration_def.attr,
+ &preempt_timeout_def.attr,
+ NULL
+};
+
+static void hw_engine_class_defaults_fini(struct drm_device *drm, void *arg)
+{
+ struct kobject *kobj = arg;
+
+ sysfs_remove_files(kobj, defaults);
+ kobject_put(kobj);
+}
+
+static int xe_add_hw_engine_class_defaults(struct xe_device *xe,
+ struct kobject *parent)
{
struct kobject *kobj;
int err = 0;
kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
if (!kobj)
- return NULL;
+ return -ENOMEM;
kobject_init(kobj, &kobj_xe_hw_engine_type);
- if (kobject_add(kobj, parent, "%s", name)) {
- kobject_put(kobj);
- return NULL;
- }
+ err = kobject_add(kobj, parent, "%s", ".defaults");
+ if (err)
+ goto err_object;
+
+ err = sysfs_create_files(kobj, defaults);
+ if (err)
+ goto err_object;
- err = drmm_add_action_or_reset(&xe->drm, kobj_xe_hw_engine_fini,
+ err = drmm_add_action_or_reset(&xe->drm, hw_engine_class_defaults_fini,
kobj);
if (err)
drm_warn(&xe->drm,
"%s: drmm_add_action_or_reset failed, err: %d\n",
__func__, err);
-
- return kobj;
+ return err;
+err_object:
+ kobject_put(kobj);
+ return err;
}
static void xe_hw_engine_sysfs_kobj_release(struct kobject *kobj)
kobject_init(kobj, &xe_hw_engine_sysfs_kobj_type);
err = kobject_add(kobj, gt->sysfs, "engines");
- if (err) {
- kobject_put(kobj);
- return err;
- }
+ if (err)
+ goto err_object;
for_each_hw_engine(hwe, gt, id) {
char name[MAX_ENGINE_CLASS_NAME_LEN];
- struct kobject *khwe;
+ struct kobj_eclass *keclass;
if (hwe->class == XE_ENGINE_CLASS_OTHER ||
hwe->class == XE_ENGINE_CLASS_MAX)
strcpy(name, "ccs");
break;
default:
- kobject_put(kobj);
- return -EINVAL;
+ err = -EINVAL;
+ goto err_object;
+ }
+
+ keclass = kobj_xe_hw_engine_class(xe, kobj, name);
+ if (!keclass) {
+ err = -EINVAL;
+ goto err_object;
}
- khwe = kobj_xe_hw_engine(xe, kobj, name);
- if (!khwe) {
- kobject_put(kobj);
- return -EINVAL;
+ keclass->eclass = hwe->eclass;
+ err = xe_add_hw_engine_class_defaults(xe, &keclass->base);
+ if (err) {
+ drm_warn(&xe->drm,
+ "Add .defaults to engines failed!, err: %d\n",
+ err);
+ goto err_object;
}
}
__func__, err);
return err;
+err_object:
+ kobject_put(kobj);
+ return err;
}
struct xe_execlist_port;
struct xe_gt;
+/**
+ * struct xe_hw_engine_class_intf - per hw engine class struct interface
+ *
+ * Contains all the hw engine properties per engine class.
+ *
+ * @sched_props: scheduling properties
+ * @defaults: default scheduling properties
+ */
+struct xe_hw_engine_class_intf {
+ /**
+ * @sched_props: scheduling properties
+ * @defaults: default scheduling properties
+ */
+ struct {
+ /** @set_job_timeout: Set job timeout in ms for engine */
+ u32 job_timeout_ms;
+ /** @job_timeout_min: Min job timeout in ms for engine */
+ u32 job_timeout_min;
+ /** @job_timeout_max: Max job timeout in ms for engine */
+ u32 job_timeout_max;
+ /** @timeslice_us: timeslice period in micro-seconds */
+ u32 timeslice_us;
+ /** @timeslice_min: min timeslice period in micro-seconds */
+ u32 timeslice_min;
+ /** @timeslice_max: max timeslice period in micro-seconds */
+ u32 timeslice_max;
+ /** @preempt_timeout_us: preemption timeout in micro-seconds */
+ u32 preempt_timeout_us;
+ /** @preempt_timeout_min: min preemption timeout in micro-seconds */
+ u32 preempt_timeout_min;
+ /** @preempt_timeout_max: max preemption timeout in micro-seconds */
+ u32 preempt_timeout_max;
+ } sched_props, defaults;
+};
+
/**
* struct xe_hw_engine - Hardware engine
*
void (*irq_handler)(struct xe_hw_engine *hwe, u16 intr_vec);
/** @engine_id: id for this hw engine */
enum xe_hw_engine_id engine_id;
+ /** @eclass: pointer to per hw engine class interface */
+ struct xe_hw_engine_class_intf *eclass;
};
/**