aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-07-17 07:14:40 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-04 04:51:10 -0400
commit6f973258b047d2913abe2bd1aad95f21cb47d5f6 (patch)
tree707b2fe599e6746ce69e8d1f07a3b9b2b844c4a4
parentf4332be72bc7a2095a21057e9db2c38bd44486b2 (diff)
drm/i915: Fix dereferencing invalid connectors in is_crtc_connector_off()
commit 2e57f47d317dd035b18634b0c602272529368fcc upstream. In commit e3de42b68478a8c95dd27520e9adead2af9477a5 Author: Imre Deak <imre.deak@intel.com> Date: Fri May 3 19:44:07 2013 +0200 drm/i915: force full modeset if the connector is in DPMS OFF mode a new function was added that walked over the set of connectors to see if any of the currently associated CRTC was switched off. This function walked an array of connectors, rather than the array of pointers to connectors contained in the drm_mode_set - i.e. it was dereferencing far past the end of the first connector. This only becomes an issue if we attempt to use a clone mode (i.e. more than one connector per CRTC) such that set->num_connectors > 1. Reported-by: Timo Aaltonen <tjaalton@ubuntu.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=65927 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Imre Deak <imre.deak@intel.com> Cc: Egbert Eich <eich@suse.de> Cc: Jesse Barnes <jbarnes@virtuousgeek.org> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/gpu/drm/i915/intel_display.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 56746dcac40f..d7ff3afbf615 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8146,15 +8146,20 @@ static void intel_set_config_restore_state(struct drm_device *dev,
8146} 8146}
8147 8147
8148static bool 8148static bool
8149is_crtc_connector_off(struct drm_crtc *crtc, struct drm_connector *connectors, 8149is_crtc_connector_off(struct drm_mode_set *set)
8150 int num_connectors)
8151{ 8150{
8152 int i; 8151 int i;
8153 8152
8154 for (i = 0; i < num_connectors; i++) 8153 if (set->num_connectors == 0)
8155 if (connectors[i].encoder && 8154 return false;
8156 connectors[i].encoder->crtc == crtc && 8155
8157 connectors[i].dpms != DRM_MODE_DPMS_ON) 8156 if (WARN_ON(set->connectors == NULL))
8157 return false;
8158
8159 for (i = 0; i < set->num_connectors; i++)
8160 if (set->connectors[i]->encoder &&
8161 set->connectors[i]->encoder->crtc == set->crtc &&
8162 set->connectors[i]->dpms != DRM_MODE_DPMS_ON)
8158 return true; 8163 return true;
8159 8164
8160 return false; 8165 return false;
@@ -8167,10 +8172,8 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
8167 8172
8168 /* We should be able to check here if the fb has the same properties 8173 /* We should be able to check here if the fb has the same properties
8169 * and then just flip_or_move it */ 8174 * and then just flip_or_move it */
8170 if (set->connectors != NULL && 8175 if (is_crtc_connector_off(set)) {
8171 is_crtc_connector_off(set->crtc, *set->connectors, 8176 config->mode_changed = true;
8172 set->num_connectors)) {
8173 config->mode_changed = true;
8174 } else if (set->crtc->fb != set->fb) { 8177 } else if (set->crtc->fb != set->fb) {
8175 /* If we have no fb then treat it as a full mode set */ 8178 /* If we have no fb then treat it as a full mode set */
8176 if (set->crtc->fb == NULL) { 8179 if (set->crtc->fb == NULL) {