diff options
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/xe/xe_exec_queue.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/xe_gt_types.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/xe_guc_submit.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/xe_hw_engine.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c | 136 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.h | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/xe_hw_engine_types.h | 37 |
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 = >->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 = >->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, + ×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) @@ -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; }; /** |