]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
drm/xe: Add sysfs for default engine scheduler properties
authorTejas Upadhyay <tejas.upadhyay@intel.com>
Fri, 4 Aug 2023 12:06:25 +0000 (17:36 +0530)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Thu, 21 Dec 2023 16:39:21 +0000 (11:39 -0500)
For each HW engine under GT we are adding defaults sysfs
entry to list all engine scheduler properties and its
default values. So that it will be easier for user to
fetch default values of these properties anytime to go
back to default.

For example,
DUT# cat /sys/class/drm/card1/device/tileN/gtN/engines/bcs/.defaults/
job_timeout_ms         preempt_timeout_us     timeslice_duration_us

where,
@job_timeout_ms: The time after which a job is removed from the scheduler.
@preempt_timeout_us: How long to wait (in microseconds) for a preemption
                     event to occur when submitting a new context.
@timeslice_duration_us: Each context is scheduled for execution for the
                        timeslice duration, before switching to the next
                        context.

V12:
   - Add missing drmm_add_action_or_reset and remove sysfs files
V11:
   - Rebase
V10:
   - Remove xe_gt.h inclusion from .h - Matt
V9 :
   - Remove jiffies for job_timeout_ms - Matt
V8 :
   - replace xe_engine with xe_hw_engine - Matt
V7 :
   - Push all errors to one error path at every places - Niranjana
   - Describe struct member to resolve kernel doc err - CI hooks
V6 :
   - Use engine class interface instead of hw engine
     in sysfs for better interfacing readability - Niranjana
V5 :
   - Scheduling props should apply per class engine not per hardware engine - Matt
   - Do not record value of job_timeout_ms if changed based on dma_fence - Matt
V4 :
   - Resolve merge conflicts - CI
V3 :
   - Rearrange code in its own file
   - Rebase
   - Update commit message to reflect tile addition
V2 :
   - Use sysfs_create_files in this patch - Niranjana
   - Handle prototype error for xe_add_engine_defaults - CI hooks
   - Remove unused member sysfs_hwe - Niranjana

Reviewed-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Tejas Upadhyay <tejas.upadhyay@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/xe/xe_exec_queue.c
drivers/gpu/drm/xe/xe_gt_types.h
drivers/gpu/drm/xe/xe_guc_submit.c
drivers/gpu/drm/xe/xe_hw_engine.c
drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c
drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.h
drivers/gpu/drm/xe/xe_hw_engine_types.h

index 1371829b9e35645c54ef0711e35810d8a4037049..41a7ae1d1a53cff4456e9da65dcca29a49825856 100644 (file)
@@ -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);
index c326932e53d799f2dc300993dd636a39b5d78644..35b8c19fa8bf53a28d7343ff1863a4750c029525 100644 (file)
@@ -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 */
index 42454c12efb30519bcea9cea2fbbc5ae970b3b92..e12cd4285e5dc6b8889835da44d5f837ad769012 100644 (file)
@@ -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,
index ead5aa2856195d632ecd0e7878b228ba0c48bed5..b7be7b0acb35e8750c8984742a5efafac08a3783 100644 (file)
@@ -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);
index 470a8c356abd9511fb0761ed80913ac3ed6edc2a..99a8197765bda8cc190cb4965f8c2a2077f3bacc 100644 (file)
@@ -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;
 }
index b3916c3cf5b3194833d5fd0b8c370d580348df86..c093f381abbe59123a04015bc8debf19bbce3b1d 100644 (file)
@@ -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
index 803d557cf5aa7aba6bba8a1fbd5173297cffd8be..97d9ba31b5fc7611d3ca862323d682a203e7d3ac 100644 (file)
@@ -63,6 +63,41 @@ struct xe_bo;
 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
  *
@@ -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;
 };
 
 /**