aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_guc_submission.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_guc_submission.c')
-rw-r--r--drivers/gpu/drm/i915/intel_guc_submission.c80
1 files changed, 27 insertions, 53 deletions
diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c
index 07b9d313b019..a81f04d46e87 100644
--- a/drivers/gpu/drm/i915/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/intel_guc_submission.c
@@ -557,16 +557,36 @@ static void inject_preempt_context(struct work_struct *work)
557 preempt_work[engine->id]); 557 preempt_work[engine->id]);
558 struct intel_guc_client *client = guc->preempt_client; 558 struct intel_guc_client *client = guc->preempt_client;
559 struct guc_stage_desc *stage_desc = __get_stage_desc(client); 559 struct guc_stage_desc *stage_desc = __get_stage_desc(client);
560 u32 ctx_desc = lower_32_bits(to_intel_context(client->owner, 560 struct intel_context *ce = to_intel_context(client->owner, engine);
561 engine)->lrc_desc);
562 u32 data[7]; 561 u32 data[7];
563 562
564 /* 563 if (!ce->ring->emit) { /* recreate upon load/resume */
565 * The ring contains commands to write GUC_PREEMPT_FINISHED into HWSP. 564 u32 addr = intel_hws_preempt_done_address(engine);
566 * See guc_fill_preempt_context(). 565 u32 *cs;
567 */ 566
567 cs = ce->ring->vaddr;
568 if (engine->id == RCS) {
569 cs = gen8_emit_ggtt_write_rcs(cs,
570 GUC_PREEMPT_FINISHED,
571 addr);
572 } else {
573 cs = gen8_emit_ggtt_write(cs,
574 GUC_PREEMPT_FINISHED,
575 addr);
576 *cs++ = MI_NOOP;
577 *cs++ = MI_NOOP;
578 }
579 *cs++ = MI_USER_INTERRUPT;
580 *cs++ = MI_NOOP;
581
582 ce->ring->emit = GUC_PREEMPT_BREADCRUMB_BYTES;
583 GEM_BUG_ON((void *)cs - ce->ring->vaddr != ce->ring->emit);
584
585 flush_ggtt_writes(ce->ring->vma);
586 }
587
568 spin_lock_irq(&client->wq_lock); 588 spin_lock_irq(&client->wq_lock);
569 guc_wq_item_append(client, engine->guc_id, ctx_desc, 589 guc_wq_item_append(client, engine->guc_id, lower_32_bits(ce->lrc_desc),
570 GUC_PREEMPT_BREADCRUMB_BYTES / sizeof(u64), 0); 590 GUC_PREEMPT_BREADCRUMB_BYTES / sizeof(u64), 0);
571 spin_unlock_irq(&client->wq_lock); 591 spin_unlock_irq(&client->wq_lock);
572 592
@@ -1044,50 +1064,6 @@ static inline bool ctx_save_restore_disabled(struct intel_context *ce)
1044#undef SR_DISABLED 1064#undef SR_DISABLED
1045} 1065}
1046 1066
1047static void guc_fill_preempt_context(struct intel_guc *guc)
1048{
1049 struct drm_i915_private *dev_priv = guc_to_i915(guc);
1050 struct intel_guc_client *client = guc->preempt_client;
1051 struct intel_engine_cs *engine;
1052 enum intel_engine_id id;
1053
1054 for_each_engine(engine, dev_priv, id) {
1055 struct intel_context *ce =
1056 to_intel_context(client->owner, engine);
1057 u32 addr = intel_hws_preempt_done_address(engine);
1058 u32 *cs;
1059
1060 GEM_BUG_ON(!ce->pin_count);
1061
1062 /*
1063 * We rely on this context image *not* being saved after
1064 * preemption. This ensures that the RING_HEAD / RING_TAIL
1065 * remain pointing at initial values forever.
1066 */
1067 GEM_BUG_ON(!ctx_save_restore_disabled(ce));
1068
1069 cs = ce->ring->vaddr;
1070 if (id == RCS) {
1071 cs = gen8_emit_ggtt_write_rcs(cs,
1072 GUC_PREEMPT_FINISHED,
1073 addr);
1074 } else {
1075 cs = gen8_emit_ggtt_write(cs,
1076 GUC_PREEMPT_FINISHED,
1077 addr);
1078 *cs++ = MI_NOOP;
1079 *cs++ = MI_NOOP;
1080 }
1081 *cs++ = MI_USER_INTERRUPT;
1082 *cs++ = MI_NOOP;
1083
1084 GEM_BUG_ON((void *)cs - ce->ring->vaddr !=
1085 GUC_PREEMPT_BREADCRUMB_BYTES);
1086
1087 flush_ggtt_writes(ce->ring->vma);
1088 }
1089}
1090
1091static int guc_clients_create(struct intel_guc *guc) 1067static int guc_clients_create(struct intel_guc *guc)
1092{ 1068{
1093 struct drm_i915_private *dev_priv = guc_to_i915(guc); 1069 struct drm_i915_private *dev_priv = guc_to_i915(guc);
@@ -1118,8 +1094,6 @@ static int guc_clients_create(struct intel_guc *guc)
1118 return PTR_ERR(client); 1094 return PTR_ERR(client);
1119 } 1095 }
1120 guc->preempt_client = client; 1096 guc->preempt_client = client;
1121
1122 guc_fill_preempt_context(guc);
1123 } 1097 }
1124 1098
1125 return 0; 1099 return 0;