diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_engine_cs.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_engine_cs.c | 203 | 
1 files changed, 175 insertions, 28 deletions
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 025e232a4205..3da4d466e332 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -82,12 +82,17 @@ static const struct engine_info {  	},  }; -static struct intel_engine_cs * +static int  intel_engine_setup(struct drm_i915_private *dev_priv,  		   enum intel_engine_id id)  {  	const struct engine_info *info = &intel_engines[id]; -	struct intel_engine_cs *engine = &dev_priv->engine[id]; +	struct intel_engine_cs *engine; + +	GEM_BUG_ON(dev_priv->engine[id]); +	engine = kzalloc(sizeof(*engine), GFP_KERNEL); +	if (!engine) +		return -ENOMEM;  	engine->id = id;  	engine->i915 = dev_priv; @@ -97,7 +102,11 @@ intel_engine_setup(struct drm_i915_private *dev_priv,  	engine->mmio_base = info->mmio_base;  	engine->irq_shift = info->irq_shift; -	return engine; +	/* Nothing to do here, execute in order of dependencies */ +	engine->schedule = NULL; + +	dev_priv->engine[id] = engine; +	return 0;  }  /** @@ -110,13 +119,16 @@ int intel_engines_init(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = to_i915(dev);  	struct intel_device_info *device_info = mkwrite_device_info(dev_priv); +	unsigned int ring_mask = INTEL_INFO(dev_priv)->ring_mask;  	unsigned int mask = 0;  	int (*init)(struct intel_engine_cs *engine); +	struct intel_engine_cs *engine; +	enum intel_engine_id id;  	unsigned int i;  	int ret; -	WARN_ON(INTEL_INFO(dev_priv)->ring_mask == 0); -	WARN_ON(INTEL_INFO(dev_priv)->ring_mask & +	WARN_ON(ring_mask == 0); +	WARN_ON(ring_mask &  		GENMASK(sizeof(mask) * BITS_PER_BYTE - 1, I915_NUM_ENGINES));  	for (i = 0; i < ARRAY_SIZE(intel_engines); i++) { @@ -131,7 +143,11 @@ int intel_engines_init(struct drm_device *dev)  		if (!init)  			continue; -		ret = init(intel_engine_setup(dev_priv, i)); +		ret = intel_engine_setup(dev_priv, i); +		if (ret) +			goto cleanup; + +		ret = init(dev_priv->engine[i]);  		if (ret)  			goto cleanup; @@ -143,7 +159,7 @@ int intel_engines_init(struct drm_device *dev)  	 * are added to the driver by a warning and disabling the forgotten  	 * engines.  	 */ -	if (WARN_ON(mask != INTEL_INFO(dev_priv)->ring_mask)) +	if (WARN_ON(mask != ring_mask))  		device_info->ring_mask = mask;  	device_info->num_rings = hweight32(mask); @@ -151,17 +167,17 @@ int intel_engines_init(struct drm_device *dev)  	return 0;  cleanup: -	for (i = 0; i < I915_NUM_ENGINES; i++) { +	for_each_engine(engine, dev_priv, id) {  		if (i915.enable_execlists) -			intel_logical_ring_cleanup(&dev_priv->engine[i]); +			intel_logical_ring_cleanup(engine);  		else -			intel_engine_cleanup(&dev_priv->engine[i]); +			intel_engine_cleanup(engine);  	}  	return ret;  } -void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno) +void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno)  {  	struct drm_i915_private *dev_priv = engine->i915; @@ -191,13 +207,13 @@ void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno)  				       I915_NUM_ENGINES * gen8_semaphore_seqno_size);  		kunmap(page);  	} -	memset(engine->semaphore.sync_seqno, 0, -	       sizeof(engine->semaphore.sync_seqno));  	intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);  	if (engine->irq_seqno_barrier)  		engine->irq_seqno_barrier(engine); -	engine->last_submitted_seqno = seqno; + +	GEM_BUG_ON(i915_gem_active_isset(&engine->timeline->last_request)); +	engine->timeline->last_submitted_seqno = seqno;  	engine->hangcheck.seqno = seqno; @@ -207,15 +223,9 @@ void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno)  	intel_engine_wakeup(engine);  } -void intel_engine_init_hangcheck(struct intel_engine_cs *engine) -{ -	memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); -} - -static void intel_engine_init_requests(struct intel_engine_cs *engine) +static void intel_engine_init_timeline(struct intel_engine_cs *engine)  { -	init_request_active(&engine->last_request, NULL); -	INIT_LIST_HEAD(&engine->request_list); +	engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id];  }  /** @@ -229,12 +239,10 @@ static void intel_engine_init_requests(struct intel_engine_cs *engine)   */  void intel_engine_setup_common(struct intel_engine_cs *engine)  { -	INIT_LIST_HEAD(&engine->execlist_queue); -	spin_lock_init(&engine->execlist_lock); - -	engine->fence_context = fence_context_alloc(1); +	engine->execlist_queue = RB_ROOT; +	engine->execlist_first = NULL; -	intel_engine_init_requests(engine); +	intel_engine_init_timeline(engine);  	intel_engine_init_hangcheck(engine);  	i915_gem_batch_pool_init(engine, &engine->batch_pool); @@ -251,7 +259,7 @@ int intel_engine_create_scratch(struct intel_engine_cs *engine, int size)  	obj = i915_gem_object_create_stolen(&engine->i915->drm, size);  	if (!obj) -		obj = i915_gem_object_create(&engine->i915->drm, size); +		obj = i915_gem_object_create_internal(engine->i915, size);  	if (IS_ERR(obj)) {  		DRM_ERROR("Failed to allocate scratch page\n");  		return PTR_ERR(obj); @@ -301,6 +309,10 @@ int intel_engine_init_common(struct intel_engine_cs *engine)  	if (ret)  		return ret; +	ret = i915_gem_render_state_init(engine); +	if (ret) +		return ret; +  	return 0;  } @@ -315,7 +327,142 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)  {  	intel_engine_cleanup_scratch(engine); +	i915_gem_render_state_fini(engine);  	intel_engine_fini_breadcrumbs(engine);  	intel_engine_cleanup_cmd_parser(engine);  	i915_gem_batch_pool_fini(&engine->batch_pool);  } + +u64 intel_engine_get_active_head(struct intel_engine_cs *engine) +{ +	struct drm_i915_private *dev_priv = engine->i915; +	u64 acthd; + +	if (INTEL_GEN(dev_priv) >= 8) +		acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base), +					 RING_ACTHD_UDW(engine->mmio_base)); +	else if (INTEL_GEN(dev_priv) >= 4) +		acthd = I915_READ(RING_ACTHD(engine->mmio_base)); +	else +		acthd = I915_READ(ACTHD); + +	return acthd; +} + +u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine) +{ +	struct drm_i915_private *dev_priv = engine->i915; +	u64 bbaddr; + +	if (INTEL_GEN(dev_priv) >= 8) +		bbaddr = I915_READ64_2x32(RING_BBADDR(engine->mmio_base), +					  RING_BBADDR_UDW(engine->mmio_base)); +	else +		bbaddr = I915_READ(RING_BBADDR(engine->mmio_base)); + +	return bbaddr; +} + +const char *i915_cache_level_str(struct drm_i915_private *i915, int type) +{ +	switch (type) { +	case I915_CACHE_NONE: return " uncached"; +	case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped"; +	case I915_CACHE_L3_LLC: return " L3+LLC"; +	case I915_CACHE_WT: return " WT"; +	default: return ""; +	} +} + +static inline uint32_t +read_subslice_reg(struct drm_i915_private *dev_priv, int slice, +		  int subslice, i915_reg_t reg) +{ +	uint32_t mcr; +	uint32_t ret; +	enum forcewake_domains fw_domains; + +	fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, +						    FW_REG_READ); +	fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, +						     GEN8_MCR_SELECTOR, +						     FW_REG_READ | FW_REG_WRITE); + +	spin_lock_irq(&dev_priv->uncore.lock); +	intel_uncore_forcewake_get__locked(dev_priv, fw_domains); + +	mcr = I915_READ_FW(GEN8_MCR_SELECTOR); +	/* +	 * The HW expects the slice and sublice selectors to be reset to 0 +	 * after reading out the registers. +	 */ +	WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK)); +	mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); +	mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice); +	I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); + +	ret = I915_READ_FW(reg); + +	mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); +	I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); + +	intel_uncore_forcewake_put__locked(dev_priv, fw_domains); +	spin_unlock_irq(&dev_priv->uncore.lock); + +	return ret; +} + +/* NB: please notice the memset */ +void intel_engine_get_instdone(struct intel_engine_cs *engine, +			       struct intel_instdone *instdone) +{ +	struct drm_i915_private *dev_priv = engine->i915; +	u32 mmio_base = engine->mmio_base; +	int slice; +	int subslice; + +	memset(instdone, 0, sizeof(*instdone)); + +	switch (INTEL_GEN(dev_priv)) { +	default: +		instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); + +		if (engine->id != RCS) +			break; + +		instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); +		for_each_instdone_slice_subslice(dev_priv, slice, subslice) { +			instdone->sampler[slice][subslice] = +				read_subslice_reg(dev_priv, slice, subslice, +						  GEN7_SAMPLER_INSTDONE); +			instdone->row[slice][subslice] = +				read_subslice_reg(dev_priv, slice, subslice, +						  GEN7_ROW_INSTDONE); +		} +		break; +	case 7: +		instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); + +		if (engine->id != RCS) +			break; + +		instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); +		instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE); +		instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE); + +		break; +	case 6: +	case 5: +	case 4: +		instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); + +		if (engine->id == RCS) +			/* HACK: Using the wrong struct member */ +			instdone->slice_common = I915_READ(GEN4_INSTDONE1); +		break; +	case 3: +	case 2: +		instdone->instdone = I915_READ(GEN2_INSTDONE); +		break; +	} +}  |