Quoting Michał Winiarski (2017-10-09 15:52:57) > diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c > index 947af576563b..418451755145 100644 > --- a/drivers/gpu/drm/i915/i915_guc_submission.c > +++ b/drivers/gpu/drm/i915/i915_guc_submission.c > @@ -558,6 +558,89 @@ static void guc_add_request(struct intel_guc *guc, > spin_unlock(&client->wq_lock); > } > > +#define GUC_PREEMPT_FINISHED 0x1 > +#define GUC_PREEMPT_BREADCRUMB_DWORDS 0x8 > +static void inject_preempt_context(struct work_struct *work) > +{ > + struct intel_engine_cs *engine = > + container_of(work, typeof(*engine), guc_preempt_work); > + struct drm_i915_private *dev_priv = engine->i915; > + struct intel_guc *guc = &dev_priv->guc; > + struct i915_guc_client *client = guc->client[PREEMPT]; > + struct intel_ring *ring = client->owner->engine[engine->id].ring; > + u32 ctx_desc = lower_32_bits(intel_lr_context_descriptor(client->owner, > + engine)); > + u32 *cs = ring->vaddr + ring->tail; > + u32 data[7]; > + > + if (engine->id == RCS) { > + cs = gen8_emit_ggtt_write_rcs(cs, GUC_PREEMPT_FINISHED, > + intel_hws_preempt_done_address(engine)); > + } else { > + cs = gen8_emit_ggtt_write(cs, GUC_PREEMPT_FINISHED, > + intel_hws_preempt_done_address(engine)); > + *cs++ = MI_NOOP; > + *cs++ = MI_NOOP; > + } > + *cs++ = MI_USER_INTERRUPT; > + *cs++ = MI_NOOP; > + > + GEM_BUG_ON(!IS_ALIGNED(ring->size, > + GUC_PREEMPT_BREADCRUMB_DWORDS * sizeof(u32))); > + GEM_BUG_ON((void*)cs - (ring->vaddr + ring->tail) != > + GUC_PREEMPT_BREADCRUMB_DWORDS * sizeof(u32)); > + > + ring->tail += GUC_PREEMPT_BREADCRUMB_DWORDS * sizeof(u32); > + ring->tail &= (ring->size - 1); > + > + if (i915_vma_is_map_and_fenceable(ring->vma)) > + POSTING_READ_FW(GUC_STATUS); > + > + spin_lock_irq(&client->wq_lock); > + guc_wq_item_append(client, engine->guc_id, ctx_desc, > + ring->tail / sizeof(u64), 0); > + spin_unlock_irq(&client->wq_lock); > + > + data[0] = INTEL_GUC_ACTION_REQUEST_PREEMPTION; > + data[1] = client->stage_id; > + data[2] = INTEL_GUC_PREEMPT_OPTION_IMMEDIATE | > + INTEL_GUC_PREEMPT_OPTION_DROP_WORK_Q | > + INTEL_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q; > + data[3] = engine->guc_id; > + data[4] = guc->client[SUBMIT]->priority; > + data[5] = guc->client[SUBMIT]->stage_id; > + data[6] = guc_ggtt_offset(guc->shared_data); > + > + if (WARN_ON(intel_guc_send(guc, data, ARRAY_SIZE(data)))) { Not speaking from experience or anything... But if this fails once, it's likely to keep failing! Ergo WARN_ON_ONCE. Broxton: [ 14.217681] [drm] INTEL_GUC_SEND: Action 0x2 failed; ret=-5 status=0xF000F000 response=0x00000010 Helpful? -Chris _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx