diff options
| author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-07-10 09:50:11 +0200 | 
|---|---|---|
| committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-09-06 08:21:30 +0200 | 
| commit | 8af6cf88a5ad7fa41d4eb700cc97f01d0bcd2a69 (patch) | |
| tree | 97475031324a623e4f46fd8ce8a4db706d26b116 | |
| parent | 9dc10f37e326d5d789929e1886b5a8089ccee5a7 (diff) | |
drm/i915: add tons of modeset state checks
... let's see whether this catches anything earlier and I can track
down a few bugs.
v2: Add more checks and also add DRM_DEBUG_KMS output so that it's
clear which connector/encoder/crtc is being checked atm. Which proved
rather useful for debugging ...
v3: Add a WARN in the common encoder dpms function, now that also
modeset changes properly update the dpms state ...
v4: Properly add a short explanation for each WARN, to avoid the need
to correlate dmesg lines with source lines accurately. Suggested by
Chris Wilson.
v5: Also dump (expected, found) for state checks (or wherever it's not
apparent from the test what exactly mismatches with expectations).
Again suggested by Chris Wilson.
v6: Due to an issue reported by Paulo Zanoni I've noticed that the
encoder checking is by far not as strict as it could and should be.
Improve this.
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 104 | 
1 files changed, 103 insertions, 1 deletions
| diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4c0ec180564f..d15fa0c6ae88 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3637,7 +3637,7 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)  	if (encoder->base.crtc)  		intel_encoder_dpms(encoder, mode);  	else -		encoder->connectors_active = false; +		WARN_ON(encoder->connectors_active != false);  	intel_connector_check_state(to_intel_connector(connector));  } @@ -6872,6 +6872,104 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)  			    base.head) \  		if (mask & (1 <<(intel_crtc)->pipe)) \ +static void +intel_modeset_check_state(struct drm_device *dev) +{ +	struct intel_crtc *crtc; +	struct intel_encoder *encoder; +	struct intel_connector *connector; + +	list_for_each_entry(connector, &dev->mode_config.connector_list, +			    base.head) { +		/* This also checks the encoder/connector hw state with the +		 * ->get_hw_state callbacks. */ +		intel_connector_check_state(connector); + +		WARN(&connector->new_encoder->base != connector->base.encoder, +		     "connector's staged encoder doesn't match current encoder\n"); +	} + +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, +			    base.head) { +		bool enabled = false; +		bool active = false; +		enum pipe pipe, tracked_pipe; + +		DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", +			      encoder->base.base.id, +			      drm_get_encoder_name(&encoder->base)); + +		WARN(&encoder->new_crtc->base != encoder->base.crtc, +		     "encoder's stage crtc doesn't match current crtc\n"); +		WARN(encoder->connectors_active && !encoder->base.crtc, +		     "encoder's active_connectors set, but no crtc\n"); + +		list_for_each_entry(connector, &dev->mode_config.connector_list, +				    base.head) { +			if (connector->base.encoder != &encoder->base) +				continue; +			enabled = true; +			if (connector->base.dpms != DRM_MODE_DPMS_OFF) +				active = true; +		} +		WARN(!!encoder->base.crtc != enabled, +		     "encoder's enabled state mismatch " +		     "(expected %i, found %i)\n", +		     !!encoder->base.crtc, enabled); +		WARN(active && !encoder->base.crtc, +		     "active encoder with no crtc\n"); + +		WARN(encoder->connectors_active != active, +		     "encoder's computed active state doesn't match tracked active state " +		     "(expected %i, found %i)\n", active, encoder->connectors_active); + +		active = encoder->get_hw_state(encoder, &pipe); +		WARN(active != encoder->connectors_active, +		     "encoder's hw state doesn't match sw tracking " +		     "(expected %i, found %i)\n", +		     encoder->connectors_active, active); + +		if (!encoder->base.crtc) +			continue; + +		tracked_pipe = to_intel_crtc(encoder->base.crtc)->pipe; +		WARN(active && pipe != tracked_pipe, +		     "active encoder's pipe doesn't match" +		     "(expected %i, found %i)\n", +		     tracked_pipe, pipe); + +	} + +	list_for_each_entry(crtc, &dev->mode_config.crtc_list, +			    base.head) { +		bool enabled = false; +		bool active = false; + +		DRM_DEBUG_KMS("[CRTC:%d]\n", +			      crtc->base.base.id); + +		WARN(crtc->active && !crtc->base.enabled, +		     "active crtc, but not enabled in sw tracking\n"); + +		list_for_each_entry(encoder, &dev->mode_config.encoder_list, +				    base.head) { +			if (encoder->base.crtc != &crtc->base) +				continue; +			enabled = true; +			if (encoder->connectors_active) +				active = true; +		} +		WARN(active != crtc->active, +		     "crtc's computed active state doesn't match tracked active state " +		     "(expected %i, found %i)\n", active, crtc->active); +		WARN(enabled != crtc->base.enabled, +		     "crtc's computed enabled state doesn't match tracked enabled state " +		     "(expected %i, found %i)\n", enabled, crtc->base.enabled); + +		assert_pipe(dev->dev_private, crtc->pipe, crtc->active); +	} +} +  bool intel_set_mode(struct drm_crtc *crtc,  		    struct drm_display_mode *mode,  		    int x, int y, struct drm_framebuffer *fb) @@ -6969,6 +7067,8 @@ done:  	if (!ret && crtc->enabled) {  		crtc->hwmode = saved_hwmode;  		crtc->mode = saved_mode; +	} else { +		intel_modeset_check_state(dev);  	}  	return ret; @@ -8147,6 +8247,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)  	}  	intel_modeset_update_staged_output_state(dev); + +	intel_modeset_check_state(dev);  }  void intel_modeset_gem_init(struct drm_device *dev) | 
