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

Daniele Ceraolo Spurio daniele.ceraolospurio at intel.com
Mon Oct 23 23:14:42 UTC 2017


<snip>

> +
> +#define GUC_PREEMPT_FINISHED 0x1
> +#define GUC_PREEMPT_BREADCRUMB_DWORDS 0x8
> +static void inject_preempt_context(struct work_struct *work)
> +{
> +	struct guc_preempt_work *preempt_work =
> +		container_of(work, typeof(*preempt_work), work);
> +	struct intel_engine_cs *engine = preempt_work->engine;
> +	struct intel_guc *guc = &engine->i915->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);
> +
> +	flush_ggtt_writes(ring->vma);
> +
> +	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 |

I was looking at how the GuC handles these flags and from what I've seen 
INTEL_GUC_PREEMPT_OPTION_IMMEDIATE doesn't seem to be used anywhere in 
GuC FW anymore (even if it still exist in the interface), so I believe 
it should be safe to drop it.

Daniele

> +		  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)))) {
> +		WRITE_ONCE(engine->execlists.preempt, false);
> +		tasklet_schedule(&engine->execlists.irq_tasklet);
> +	}
> +}


More information about the Intel-gfx mailing list