diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 93 | 
1 files changed, 43 insertions, 50 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index dec9e58545a1..cc484b56eeaa 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3427,26 +3427,6 @@ static void intel_complete_page_flips(struct drm_i915_private *dev_priv)  		intel_finish_page_flip_cs(dev_priv, crtc->pipe);  } -static void intel_update_primary_planes(struct drm_device *dev) -{ -	struct drm_crtc *crtc; - -	for_each_crtc(dev, crtc) { -		struct intel_plane *plane = to_intel_plane(crtc->primary); -		struct intel_plane_state *plane_state = -			to_intel_plane_state(plane->base.state); - -		if (plane_state->base.visible) { -			trace_intel_update_plane(&plane->base, -						 to_intel_crtc(crtc)); - -			plane->update_plane(plane, -					    to_intel_crtc_state(crtc->state), -					    plane_state); -		} -	} -} -  static int  __intel_display_resume(struct drm_device *dev,  		       struct drm_atomic_state *state, @@ -3499,6 +3479,19 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)  	struct drm_atomic_state *state;  	int ret; + +	/* reset doesn't touch the display */ +	if (!i915.force_reset_modeset_test && +	    !gpu_reset_clobbers_display(dev_priv)) +		return; + +	/* We have a modeset vs reset deadlock, defensively unbreak it. +	 * +	 * FIXME: We can do a _lot_ better, this is just a first iteration. +	 */ +	i915_gem_set_wedged(dev_priv); +	DRM_DEBUG_DRIVER("Wedging GPU to avoid deadlocks with pending modeset updates\n"); +  	/*  	 * Need mode_config.mutex so that we don't  	 * trample ongoing ->detect() and whatnot. @@ -3512,12 +3505,6 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)  		drm_modeset_backoff(ctx);  	} - -	/* reset doesn't touch the display, but flips might get nuked anyway, */ -	if (!i915.force_reset_modeset_test && -	    !gpu_reset_clobbers_display(dev_priv)) -		return; -  	/*  	 * Disabling the crtcs gracefully seems nicer. Also the  	 * g33 docs say we should at least disable all the planes. @@ -3547,6 +3534,14 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)  	struct drm_atomic_state *state = dev_priv->modeset_restore_state;  	int ret; +	/* reset doesn't touch the display */ +	if (!i915.force_reset_modeset_test && +	    !gpu_reset_clobbers_display(dev_priv)) +		return; + +	if (!state) +		goto unlock; +  	/*  	 * Flips in the rings will be nuked by the reset,  	 * so complete all pending flips so that user space @@ -3558,22 +3553,10 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)  	/* reset doesn't touch the display */  	if (!gpu_reset_clobbers_display(dev_priv)) { -		if (!state) { -			/* -			 * Flips in the rings have been nuked by the reset, -			 * so update the base address of all primary -			 * planes to the the last fb to make sure we're -			 * showing the correct fb after a reset. -			 * -			 * FIXME: Atomic will make this obsolete since we won't schedule -			 * CS-based flips (which might get lost in gpu resets) any more. -			 */ -			intel_update_primary_planes(dev); -		} else { -			ret = __intel_display_resume(dev, state, ctx); +		/* for testing only restore the display */ +		ret = __intel_display_resume(dev, state, ctx);  			if (ret)  				DRM_ERROR("Restoring old state failed with %i\n", ret); -		}  	} else {  		/*  		 * The display has been reset as well, @@ -3597,8 +3580,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)  		intel_hpd_init(dev_priv);  	} -	if (state) -		drm_atomic_state_put(state); +	drm_atomic_state_put(state); +unlock:  	drm_modeset_drop_locks(ctx);  	drm_modeset_acquire_fini(ctx);  	mutex_unlock(&dev->mode_config.mutex); @@ -9117,6 +9100,13 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,  	u64 power_domain_mask;  	bool active; +	if (INTEL_GEN(dev_priv) >= 9) { +		intel_crtc_init_scalers(crtc, pipe_config); + +		pipe_config->scaler_state.scaler_id = -1; +		pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX); +	} +  	power_domain = POWER_DOMAIN_PIPE(crtc->pipe);  	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))  		return false; @@ -9145,13 +9135,6 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,  	pipe_config->gamma_mode =  		I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK; -	if (INTEL_GEN(dev_priv) >= 9) { -		intel_crtc_init_scalers(crtc, pipe_config); - -		pipe_config->scaler_state.scaler_id = -1; -		pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX); -	} -  	power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);  	if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {  		power_domain_mask |= BIT_ULL(power_domain); @@ -9540,7 +9523,16 @@ static void i9xx_update_cursor(struct intel_plane *plane,  	 * On some platforms writing CURCNTR first will also  	 * cause CURPOS to be armed by the CURBASE write.  	 * Without the CURCNTR write the CURPOS write would -	 * arm itself. +	 * arm itself. Thus we always start the full update +	 * with a CURCNTR write. +	 * +	 * On other platforms CURPOS always requires the +	 * CURBASE write to arm the update. Additonally +	 * a write to any of the cursor register will cancel +	 * an already armed cursor update. Thus leaving out +	 * the CURBASE write after CURPOS could lead to a +	 * cursor that doesn't appear to move, or even change +	 * shape. Thus we always write CURBASE.  	 *  	 * CURCNTR and CUR_FBC_CTL are always  	 * armed by the CURBASE write only. @@ -9559,6 +9551,7 @@ static void i9xx_update_cursor(struct intel_plane *plane,  		plane->cursor.cntl = cntl;  	} else {  		I915_WRITE_FW(CURPOS(pipe), pos); +		I915_WRITE_FW(CURBASE(pipe), base);  	}  	POSTING_READ_FW(CURBASE(pipe));  |