summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/xe/xe_exec_queue.c6
-rw-r--r--drivers/gpu/drm/xe/xe_gt_types.h3
-rw-r--r--drivers/gpu/drm/xe/xe_guc_submit.c3
-rw-r--r--drivers/gpu/drm/xe/xe_hw_engine.c9
-rw-r--r--drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c136
-rw-r--r--drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.h22
-rw-r--r--drivers/gpu/drm/xe/xe_hw_engine_types.h37
7 files changed, 190 insertions, 26 deletions
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index 1371829b9e35..41a7ae1d1a53 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -53,9 +53,9 @@ static struct xe_exec_queue *__xe_exec_queue_create(struct xe_device *xe,
INIT_LIST_HEAD(&q->compute.link);
INIT_LIST_HEAD(&q->multi_gt_link);
- /* FIXME: Wire up to configurable default value */
- q->sched_props.timeslice_us = 1 * 1000;
- q->sched_props.preempt_timeout_us = 640 * 1000;
+ q->sched_props.timeslice_us = hwe->eclass->sched_props.timeslice_us;
+ q->sched_props.preempt_timeout_us =
+ hwe->eclass->sched_props.preempt_timeout_us;
if (xe_exec_queue_is_parallel(q)) {
q->parallel.composite_fence_ctx = dma_fence_context_alloc(1);
diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h
index c326932e53d7..35b8c19fa8bf 100644
--- a/drivers/gpu/drm/xe/xe_gt_types.h
+++ b/drivers/gpu/drm/xe/xe_gt_types.h
@@ -286,6 +286,9 @@ struct xe_gt {
/** @hw_engines: hardware engines on the GT */
struct xe_hw_engine hw_engines[XE_NUM_HW_ENGINES];
+ /** @eclass: per hardware engine class interface on the GT */
+ struct xe_hw_engine_class_intf eclass[XE_ENGINE_CLASS_MAX];
+
/** @pcode: GT's PCODE */
struct {
/** @lock: protecting GT's PCODE mailbox data */
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 42454c12efb3..e12cd4285e5d 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -1132,7 +1132,8 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
ge->q = q;
init_waitqueue_head(&ge->suspend_wait);
- timeout = xe_vm_no_dma_fences(q->vm) ? MAX_SCHEDULE_TIMEOUT : HZ * 5;
+ timeout = xe_vm_no_dma_fences(q->vm) ? MAX_SCHEDULE_TIMEOUT :
+ q->hwe->eclass->sched_props.job_timeout_ms;
err = xe_sched_init(&ge->sched, &drm_sched_ops, &xe_sched_ops, NULL,
q->lrc[0].ring.size / MAX_JOB_SIZE_BYTES,
64, timeout, guc_to_gt(guc)->ordered_wq, NULL,
diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c
index ead5aa285619..b7be7b0acb35 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine.c
+++ b/drivers/gpu/drm/xe/xe_hw_engine.c
@@ -362,6 +362,15 @@ static void hw_engine_init_early(struct xe_gt *gt, struct xe_hw_engine *hwe,
hwe->fence_irq = &gt->fence_irq[info->class];
hwe->engine_id = id;
+ if (!gt->eclass[hwe->class].sched_props.job_timeout_ms) {
+ gt->eclass[hwe->class].sched_props.job_timeout_ms = 5 * 1000;
+ gt->eclass[hwe->class].sched_props.timeslice_us = 1 * 1000;
+ gt->eclass[hwe->class].sched_props.preempt_timeout_us = 640 * 1000;
+ /* Record default props */
+ gt->eclass[hwe->class].defaults = gt->eclass[hwe->class].sched_props;
+ }
+ hwe->eclass = &gt->eclass[hwe->class];
+
xe_reg_sr_init(&hwe->reg_sr, hwe->name, gt_to_xe(gt));
xe_wa_process_engine(hwe);
hw_engine_setup_default_state(hwe);
diff --git a/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c b/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c
index 470a8c356abd..99a8197765bd 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c
+++ b/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c
@@ -11,6 +11,9 @@
#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);
@@ -21,37 +24,116 @@ static const struct kobj_type kobj_xe_hw_engine_type = {
.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,
+ &timeslice_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)
@@ -96,14 +178,12 @@ int xe_hw_engine_class_sysfs_init(struct xe_gt *gt)
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)
@@ -131,14 +211,23 @@ int xe_hw_engine_class_sysfs_init(struct xe_gt *gt)
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;
}
}
@@ -150,4 +239,7 @@ int xe_hw_engine_class_sysfs_init(struct xe_gt *gt)
__func__, err);
return err;
+err_object:
+ kobject_put(kobj);
+ return err;
}
diff --git a/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.h b/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.h
index b3916c3cf5b3..c093f381abbe 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.h
+++ b/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.h
@@ -6,8 +6,30 @@
#ifndef _XE_ENGINE_CLASS_SYSFS_H_
#define _XE_ENGINE_CLASS_SYSFS_H__
+#include <linux/kobject.h>
+
struct xe_gt;
+struct xe_hw_engine_class_intf;
int xe_hw_engine_class_sysfs_init(struct xe_gt *gt);
+/**
+ * struct kobj_eclass - A eclass's kobject struct that connects the kobject and the
+ * eclass.
+ *
+ * When dealing with multiple eclass, this struct helps to understand which eclass
+ * needs to be addressed on a given sysfs call.
+ */
+struct kobj_eclass {
+ /** @base: The actual kobject */
+ struct kobject base;
+ /** @eclass: A pointer to the hw engine class interface */
+ struct xe_hw_engine_class_intf *eclass;
+};
+
+static inline struct xe_hw_engine_class_intf *kobj_to_eclass(struct kobject *kobj)
+{
+ return container_of(kobj, struct kobj_eclass, base)->eclass;
+}
+
#endif
diff --git a/drivers/gpu/drm/xe/xe_hw_engine_types.h b/drivers/gpu/drm/xe/xe_hw_engine_types.h
index 803d557cf5aa..97d9ba31b5fc 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine_types.h
+++ b/drivers/gpu/drm/xe/xe_hw_engine_types.h
@@ -64,6 +64,41 @@ 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
*
* Contains all the hardware engine state for physical instances.
@@ -107,6 +142,8 @@ struct xe_hw_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;
};
/**