diff options
Diffstat (limited to 'drivers/gpu/drm/i915/gt/intel_engine_cs.c')
| -rw-r--r-- | drivers/gpu/drm/i915/gt/intel_engine_cs.c | 103 | 
1 files changed, 62 insertions, 41 deletions
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index c33e0d72d670..d4e29da74612 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -894,6 +894,24 @@ static intel_engine_mask_t init_engine_mask(struct intel_gt *gt)  	engine_mask_apply_compute_fuses(gt);  	engine_mask_apply_copy_fuses(gt); +	/* +	 * The only use of the GSC CS is to load and communicate with the GSC +	 * FW, so we have no use for it if we don't have the FW. +	 * +	 * IMPORTANT: in cases where we don't have the GSC FW, we have a +	 * catch-22 situation that breaks media C6 due to 2 requirements: +	 * 1) once turned on, the GSC power well will not go to sleep unless the +	 *    GSC FW is loaded. +	 * 2) to enable idling (which is required for media C6) we need to +	 *    initialize the IDLE_MSG register for the GSC CS and do at least 1 +	 *    submission, which will wake up the GSC power well. +	 */ +	if (__HAS_ENGINE(info->engine_mask, GSC0) && !intel_uc_wants_gsc_uc(>->uc)) { +		drm_notice(>->i915->drm, +			   "No GSC FW selected, disabling GSC CS and media C6\n"); +		info->engine_mask &= ~BIT(GSC0); +	} +  	return info->engine_mask;  } @@ -1476,10 +1494,12 @@ static int __intel_engine_stop_cs(struct intel_engine_cs *engine,  	intel_uncore_write_fw(uncore, mode, _MASKED_BIT_ENABLE(STOP_RING));  	/* -	 * Wa_22011802037 : gen11, gen12, Prior to doing a reset, ensure CS is +	 * Wa_22011802037: Prior to doing a reset, ensure CS is  	 * stopped, set ring stop bit and prefetch disable bit to halt CS  	 */ -	if (IS_GRAPHICS_VER(engine->i915, 11, 12)) +	if (IS_MTL_GRAPHICS_STEP(engine->i915, M, STEP_A0, STEP_B0) || +	    (GRAPHICS_VER(engine->i915) >= 11 && +	    GRAPHICS_VER_FULL(engine->i915) < IP_VER(12, 70)))  		intel_uncore_write_fw(uncore, RING_MODE_GEN7(engine->mmio_base),  				      _MASKED_BIT_ENABLE(GEN12_GFX_PREFETCH_DISABLE)); @@ -1564,11 +1584,8 @@ static u32 __cs_pending_mi_force_wakes(struct intel_engine_cs *engine)  	};  	u32 val; -	if (!_reg[engine->id].reg) { -		drm_err(&engine->i915->drm, -			"MSG IDLE undefined for engine id %u\n", engine->id); +	if (!_reg[engine->id].reg)  		return 0; -	}  	val = intel_uncore_read(engine->uncore, _reg[engine->id]); @@ -2094,17 +2111,6 @@ static void print_request_ring(struct drm_printer *m, struct i915_request *rq)  	}  } -static unsigned long list_count(struct list_head *list) -{ -	struct list_head *pos; -	unsigned long count = 0; - -	list_for_each(pos, list) -		count++; - -	return count; -} -  static unsigned long read_ul(void *p, size_t x)  {  	return *(unsigned long *)(p + x); @@ -2196,11 +2202,11 @@ void intel_engine_dump_active_requests(struct list_head *requests,  	}  } -static void engine_dump_active_requests(struct intel_engine_cs *engine, struct drm_printer *m) +static void engine_dump_active_requests(struct intel_engine_cs *engine, +					struct drm_printer *m)  { +	struct intel_context *hung_ce = NULL;  	struct i915_request *hung_rq = NULL; -	struct intel_context *ce; -	bool guc;  	/*  	 * No need for an engine->irq_seqno_barrier() before the seqno reads. @@ -2209,27 +2215,22 @@ static void engine_dump_active_requests(struct intel_engine_cs *engine, struct d  	 * But the intention here is just to report an instantaneous snapshot  	 * so that's fine.  	 */ -	lockdep_assert_held(&engine->sched_engine->lock); +	intel_engine_get_hung_entity(engine, &hung_ce, &hung_rq);  	drm_printf(m, "\tRequests:\n"); -	guc = intel_uc_uses_guc_submission(&engine->gt->uc); -	if (guc) { -		ce = intel_engine_get_hung_context(engine); -		if (ce) -			hung_rq = intel_context_find_active_request(ce); -	} else { -		hung_rq = intel_engine_execlist_find_hung_request(engine); -	} -  	if (hung_rq)  		engine_dump_request(hung_rq, m, "\t\thung"); +	else if (hung_ce) +		drm_printf(m, "\t\tGot hung ce but no hung rq!\n"); -	if (guc) +	if (intel_uc_uses_guc_submission(&engine->gt->uc))  		intel_guc_dump_active_requests(engine, hung_rq, m);  	else -		intel_engine_dump_active_requests(&engine->sched_engine->requests, -						  hung_rq, m); +		intel_execlists_dump_active_requests(engine, hung_rq, m); + +	if (hung_rq) +		i915_request_put(hung_rq);  }  void intel_engine_dump(struct intel_engine_cs *engine, @@ -2239,7 +2240,6 @@ void intel_engine_dump(struct intel_engine_cs *engine,  	struct i915_gpu_error * const error = &engine->i915->gpu_error;  	struct i915_request *rq;  	intel_wakeref_t wakeref; -	unsigned long flags;  	ktime_t dummy;  	if (header) { @@ -2276,13 +2276,8 @@ void intel_engine_dump(struct intel_engine_cs *engine,  		   i915_reset_count(error));  	print_properties(engine, m); -	spin_lock_irqsave(&engine->sched_engine->lock, flags);  	engine_dump_active_requests(engine, m); -	drm_printf(m, "\tOn hold?: %lu\n", -		   list_count(&engine->sched_engine->hold)); -	spin_unlock_irqrestore(&engine->sched_engine->lock, flags); -  	drm_printf(m, "\tMMIO base:  0x%08x\n", engine->mmio_base);  	wakeref = intel_runtime_pm_get_if_in_use(engine->uncore->rpm);  	if (wakeref) { @@ -2328,8 +2323,7 @@ intel_engine_create_virtual(struct intel_engine_cs **siblings,  	return siblings[0]->cops->create_virtual(siblings, count, flags);  } -struct i915_request * -intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine) +static struct i915_request *engine_execlist_find_hung_request(struct intel_engine_cs *engine)  {  	struct i915_request *request, *active = NULL; @@ -2381,6 +2375,33 @@ intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine)  	return active;  } +void intel_engine_get_hung_entity(struct intel_engine_cs *engine, +				  struct intel_context **ce, struct i915_request **rq) +{ +	unsigned long flags; + +	*ce = intel_engine_get_hung_context(engine); +	if (*ce) { +		intel_engine_clear_hung_context(engine); + +		*rq = intel_context_get_active_request(*ce); +		return; +	} + +	/* +	 * Getting here with GuC enabled means it is a forced error capture +	 * with no actual hang. So, no need to attempt the execlist search. +	 */ +	if (intel_uc_uses_guc_submission(&engine->gt->uc)) +		return; + +	spin_lock_irqsave(&engine->sched_engine->lock, flags); +	*rq = engine_execlist_find_hung_request(engine); +	if (*rq) +		*rq = i915_request_get_rcu(*rq); +	spin_unlock_irqrestore(&engine->sched_engine->lock, flags); +} +  void xehp_enable_ccs_engines(struct intel_engine_cs *engine)  {  	/*  |