[PATCH 01/37] drm/i915/guc: Clear preempt status before use

Chris Wilson chris at chris-wilson.co.uk
Mon Oct 15 10:28:38 UTC 2018


---
 drivers/gpu/drm/i915/intel_guc.h            |  4 ++-
 drivers/gpu/drm/i915/intel_guc_submission.c | 33 +++++++++++----------
 2 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 0f1c4f9ebfd8..5703e62a3d33 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -34,6 +34,8 @@
 #include "intel_uc_fw.h"
 #include "i915_vma.h"
 
+struct guc_shared_ctx_data;
+
 struct guc_preempt_work {
 	struct work_struct work;
 	struct intel_engine_cs *engine;
@@ -62,7 +64,7 @@ struct intel_guc {
 	void *stage_desc_pool_vaddr;
 	struct ida stage_ids;
 	struct i915_vma *shared_data;
-	void *shared_data_vaddr;
+	struct guc_shared_ctx_data *shared_data_vaddr;
 
 	struct intel_guc_client *execbuf_client;
 	struct intel_guc_client *preempt_client;
diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c
index eae668442ebe..fb0499f80b62 100644
--- a/drivers/gpu/drm/i915/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/intel_guc_submission.c
@@ -555,6 +555,8 @@ static void inject_preempt_context(struct work_struct *work)
 	struct intel_guc_client *client = guc->preempt_client;
 	struct guc_stage_desc *stage_desc = __get_stage_desc(client);
 	struct intel_context *ce = to_intel_context(client->owner, engine);
+	struct guc_ctx_report *report =
+		&guc->shared_data_vaddr->preempt_ctx_report[engine->guc_id];
 	u32 data[7];
 
 	if (!ce->ring->emit) { /* recreate upon load/resume */
@@ -587,6 +589,14 @@ static void inject_preempt_context(struct work_struct *work)
 			   GUC_PREEMPT_BREADCRUMB_BYTES / sizeof(u64), 0);
 	spin_unlock_irq(&client->wq_lock);
 
+	/*
+	 * GuC is expecting that we're also going to clear the affected context
+	 * counter, let's also reset the return status to not depend on GuC
+	 * resetting it after recieving another preempt action
+	 */
+	report->affected_count = 0;
+	report->report_return_status = INTEL_GUC_REPORT_STATUS_UNKNOWN;
+
 	/*
 	 * If GuC firmware performs an engine reset while that engine had
 	 * a preemption pending, it will set the terminated attribute bit
@@ -629,20 +639,12 @@ static void inject_preempt_context(struct work_struct *work)
 static void wait_for_guc_preempt_report(struct intel_engine_cs *engine)
 {
 	struct intel_guc *guc = &engine->i915->guc;
-	struct guc_shared_ctx_data *data = guc->shared_data_vaddr;
 	struct guc_ctx_report *report =
-		&data->preempt_ctx_report[engine->guc_id];
+		&guc->shared_data_vaddr->preempt_ctx_report[engine->guc_id];
 
-	WARN_ON(wait_for_atomic(report->report_return_status ==
+	WARN_ON(wait_for_atomic(READ_ONCE(report->report_return_status) ==
 				INTEL_GUC_REPORT_STATUS_COMPLETE,
 				GUC_PREEMPT_POSTPROCESS_DELAY_MS));
-	/*
-	 * GuC is expecting that we're also going to clear the affected context
-	 * counter, let's also reset the return status to not depend on GuC
-	 * resetting it after recieving another preempt action
-	 */
-	report->affected_count = 0;
-	report->report_return_status = INTEL_GUC_REPORT_STATUS_UNKNOWN;
 }
 
 static void complete_preempt_context(struct intel_engine_cs *engine)
@@ -654,11 +656,10 @@ static void complete_preempt_context(struct intel_engine_cs *engine)
 	if (inject_preempt_hang(execlists))
 		return;
 
+	wait_for_guc_preempt_report(engine);
+
 	execlists_cancel_port_requests(execlists);
 	execlists_unwind_incomplete_requests(execlists);
-
-	wait_for_guc_preempt_report(engine);
-	intel_write_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX, 0);
 }
 
 /**
@@ -726,6 +727,9 @@ static bool __guc_dequeue(struct intel_engine_cs *engine)
 			int prio = execlists->queue_priority;
 
 			if (__execlists_need_preempt(prio, port_prio(port))) {
+				intel_write_status_page(engine,
+							I915_GEM_HWS_PREEMPT_INDEX,
+							0);
 				execlists_set_active(execlists,
 						     EXECLISTS_ACTIVE_PREEMPT);
 				queue_work(engine->i915->guc.preempt_wq,
@@ -816,8 +820,7 @@ static void guc_submission_tasklet(unsigned long data)
 	}
 
 	if (execlists_is_active(execlists, EXECLISTS_ACTIVE_PREEMPT) &&
-	    intel_read_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX) ==
-	    GUC_PREEMPT_FINISHED)
+	    intel_read_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX))
 		complete_preempt_context(engine);
 
 	if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_PREEMPT))
-- 
2.19.1



More information about the Intel-gfx-trybot mailing list