drm/i915/gt: Expose reset stop timeout via sysfs
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 28 Feb 2020 13:17:14 +0000 (13:17 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 28 Feb 2020 22:03:43 +0000 (22:03 +0000)
When we allow ourselves to sleep before a GPU reset after disabling
submission, even for a few milliseconds, gives an innocent context the
opportunity to clear the GPU before the reset occurs. However, how long
to sleep depends on the typical non-preemptible duration (a similar
problem to determining the ideal preempt-reset timeout or even the
heartbeat interval). As this seems of a hard policy decision, punt it to
userspace.

The timeout can be adjusted using

/sys/class/drm/card?/engine/*/stop_timeout_ms

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Jon Bloomfield <jon.bloomfield@intel.com>
Reviewed-by: Steve Carbonari <steven.carbonari@intel.com>
Tested-by: Steve Carbonari <steven.carbonari@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200228131716.3243616-5-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/Kconfig.profile
drivers/gpu/drm/i915/gt/sysfs_engines.c

index 9ee3b59685b903a456796708533094bb28b5ad71..5f4ec3aec1d287b7d2c66f9c46dae83d0447035c 100644 (file)
@@ -63,6 +63,9 @@ config DRM_I915_STOP_TIMEOUT
          that the reset itself may take longer and so be more disruptive to
          interactive or low latency workloads.
 
+         This is adjustable via
+         /sys/class/drm/card?/engine/*/stop_timeout_ms
+
 config DRM_I915_TIMESLICE_DURATION
        int "Scheduling quantum for userspace batches (ms, jiffy granularity)"
        default 1 # milliseconds
index 619c43d1172d8390518c8319933f8c87e482001e..b7b62a439ddd8c6edece86eab13c328920cf2998 100644 (file)
@@ -232,6 +232,45 @@ timeslice_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 static struct kobj_attribute timeslice_duration_attr =
 __ATTR(timeslice_duration_ms, 0644, timeslice_show, timeslice_store);
 
+static ssize_t
+stop_store(struct kobject *kobj, struct kobj_attribute *attr,
+          const char *buf, size_t count)
+{
+       struct intel_engine_cs *engine = kobj_to_engine(kobj);
+       unsigned long long duration;
+       int err;
+
+       /*
+        * When we allow ourselves to sleep before a GPU reset after disabling
+        * submission, even for a few milliseconds, gives an innocent context
+        * the opportunity to clear the GPU before the reset occurs. However,
+        * how long to sleep depends on the typical non-preemptible duration
+        * (a similar problem to determining the ideal preempt-reset timeout
+        * or even the heartbeat interval).
+        */
+
+       err = kstrtoull(buf, 0, &duration);
+       if (err)
+               return err;
+
+       if (duration > jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT))
+               return -EINVAL;
+
+       WRITE_ONCE(engine->props.stop_timeout_ms, duration);
+       return count;
+}
+
+static ssize_t
+stop_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+       struct intel_engine_cs *engine = kobj_to_engine(kobj);
+
+       return sprintf(buf, "%lu\n", engine->props.stop_timeout_ms);
+}
+
+static struct kobj_attribute stop_timeout_attr =
+__ATTR(stop_timeout_ms, 0644, stop_show, stop_store);
+
 static void kobj_engine_release(struct kobject *kobj)
 {
        kfree(kobj);
@@ -273,6 +312,7 @@ void intel_engines_add_sysfs(struct drm_i915_private *i915)
                &caps_attr.attr,
                &all_caps_attr.attr,
                &max_spin_attr.attr,
+               &stop_timeout_attr.attr,
                NULL
        };