aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff McGee <[email protected]>2017-11-01 15:16:30 -0700
committerChris Wilson <[email protected]>2017-11-02 08:07:22 +0000
commit6d5646006f66880574c75c4e142ef370b4503af3 (patch)
tree897dd67bb2ca8b74b153d2596487e1b30a2cf78a
parent6e7406db8c3a6998e84a605d3e1e04b166e795d1 (diff)
drm/i915/guc: Clear terminated attribute bit on GuC preemption context
If GuC firmware performs an engine reset while that engine had a preemption pending, it will set the terminated attribute bit on our preemption stage descriptor. GuC firmware retains all pending work items for a high-priority GuC client, unlike the normal-priority GuC client where work items are dropped. It wants to make sure the preempt- to-idle work doesn't run when scheduling resumes, and uses this bit to inform its scheduler and presumably us as well. Our job is to clear it for the next preemption after reset, otherwise that and future preemptions will never complete. We'll just clear it every time. Signed-off-by: Jeff McGee <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] Reviewed-by: Michel Thierry <[email protected]> Signed-off-by: Chris Wilson <[email protected]>
-rw-r--r--drivers/gpu/drm/i915/i915_guc_submission.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 3049a0781b88..d14c1342f09d 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -590,6 +590,7 @@ static void inject_preempt_context(struct work_struct *work)
struct intel_guc *guc = container_of(preempt_work, typeof(*guc),
preempt_work[engine->id]);
struct i915_guc_client *client = guc->preempt_client;
+ struct guc_stage_desc *stage_desc = __get_stage_desc(client);
struct intel_ring *ring = client->owner->engine[engine->id].ring;
u32 ctx_desc = lower_32_bits(intel_lr_context_descriptor(client->owner,
engine));
@@ -623,6 +624,20 @@ static void inject_preempt_context(struct work_struct *work)
ring->tail / sizeof(u64), 0);
spin_unlock_irq(&client->wq_lock);
+ /*
+ * If GuC firmware performs an engine reset while that engine had
+ * a preemption pending, it will set the terminated attribute bit
+ * on our preemption stage descriptor. GuC firmware retains all
+ * pending work items for a high-priority GuC client, unlike the
+ * normal-priority GuC client where work items are dropped. It
+ * wants to make sure the preempt-to-idle work doesn't run when
+ * scheduling resumes, and uses this bit to inform its scheduler
+ * and presumably us as well. Our job is to clear it for the next
+ * preemption after reset, otherwise that and future preemptions
+ * will never complete. We'll just clear it every time.
+ */
+ stage_desc->attribute &= ~GUC_STAGE_DESC_ATTR_TERMINATED;
+
data[0] = INTEL_GUC_ACTION_REQUEST_PREEMPTION;
data[1] = client->stage_id;
data[2] = INTEL_GUC_PREEMPT_OPTION_DROP_WORK_Q |