[Intel-gfx] [PATCH v2 11/12] drm/i915/guc: Preemption! With GuC

Chris Wilson chris at chris-wilson.co.uk
Mon Oct 9 20:32:07 UTC 2017


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


More information about the Intel-gfx mailing list