summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2020-02-28 13:17:15 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2020-02-28 22:03:46 +0000
commitdb3d8338bacbfc734d246eaccfbe5b19ad81d7d4 (patch)
treed358edbe0fd333e37bfcb3d895bd564ee7406e06
parent72338a1f5ef8a480184aac48bcc8e9f7d4d0d0a5 (diff)
downloadlinux-stable-db3d8338bacbfc734d246eaccfbe5b19ad81d7d4.tar.gz
linux-stable-db3d8338bacbfc734d246eaccfbe5b19ad81d7d4.tar.bz2
linux-stable-db3d8338bacbfc734d246eaccfbe5b19ad81d7d4.zip
drm/i915/gt: Expose preempt reset timeout via sysfs
After initialising a preemption request, we give the current resident a small amount of time to vacate the GPU. The preemption request is for a higher priority context and should be immediate to maintain high quality of service (and avoid priority inversion). However, the preemption granularity of the GPU can be quite coarse and so we need a compromise. The preempt timeout can be adjusted per-engine using, /sys/class/drm/card?/engine/*/preempt_timeout_ms and can be disabled by setting it to 0. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> 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-6-chris@chris-wilson.co.uk
-rw-r--r--drivers/gpu/drm/i915/Kconfig.profile3
-rw-r--r--drivers/gpu/drm/i915/gt/sysfs_engines.c48
2 files changed, 51 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/Kconfig.profile b/drivers/gpu/drm/i915/Kconfig.profile
index 5f4ec3aec1d2..1f4e98a8532f 100644
--- a/drivers/gpu/drm/i915/Kconfig.profile
+++ b/drivers/gpu/drm/i915/Kconfig.profile
@@ -33,6 +33,9 @@ config DRM_I915_PREEMPT_TIMEOUT
expires, the HW will be reset to allow the more important context
to execute.
+ This is adjustable via
+ /sys/class/drm/card?/engine/*/preempt_timeout_ms
+
May be 0 to disable the timeout.
config DRM_I915_MAX_REQUEST_BUSYWAIT
diff --git a/drivers/gpu/drm/i915/gt/sysfs_engines.c b/drivers/gpu/drm/i915/gt/sysfs_engines.c
index b7b62a439ddd..0c109adb18b8 100644
--- a/drivers/gpu/drm/i915/gt/sysfs_engines.c
+++ b/drivers/gpu/drm/i915/gt/sysfs_engines.c
@@ -271,6 +271,50 @@ stop_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
static struct kobj_attribute stop_timeout_attr =
__ATTR(stop_timeout_ms, 0644, stop_show, stop_store);
+static ssize_t
+preempt_timeout_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 timeout;
+ int err;
+
+ /*
+ * After initialising a preemption request, we give the current
+ * resident a small amount of time to vacate the GPU. The preemption
+ * request is for a higher priority context and should be immediate to
+ * maintain high quality of service (and avoid priority inversion).
+ * However, the preemption granularity of the GPU can be quite coarse
+ * and so we need a compromise.
+ */
+
+ err = kstrtoull(buf, 0, &timeout);
+ if (err)
+ return err;
+
+ if (timeout > jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT))
+ return -EINVAL;
+
+ WRITE_ONCE(engine->props.preempt_timeout_ms, timeout);
+
+ if (READ_ONCE(engine->execlists.pending[0]))
+ set_timer_ms(&engine->execlists.preempt, timeout);
+
+ return count;
+}
+
+static ssize_t
+preempt_timeout_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.preempt_timeout_ms);
+}
+
+static struct kobj_attribute preempt_timeout_attr =
+__ATTR(preempt_timeout_ms, 0644, preempt_timeout_show, preempt_timeout_store);
+
static void kobj_engine_release(struct kobject *kobj)
{
kfree(kobj);
@@ -338,6 +382,10 @@ void intel_engines_add_sysfs(struct drm_i915_private *i915)
sysfs_create_file(kobj, &timeslice_duration_attr.attr))
goto err_engine;
+ if (intel_engine_has_preempt_reset(engine) &&
+ sysfs_create_file(kobj, &preempt_timeout_attr.attr))
+ goto err_engine;
+
if (0) {
err_object:
kobject_put(kobj);