aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-07-17 07:14:40 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-07-17 07:24:18 -0400
commit2e57f47d317dd035b18634b0c602272529368fcc (patch)
tree57a058d51bc2480e53c039c25c9f5c730070e26b
parent35c95375f69ceec721fea67a0532bc17ceb5cf64 (diff)
drm/i915: Fix dereferencing invalid connectors in is_crtc_connector_off()
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> Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-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 76b01c16a0e8..76b034be2c7c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8540,15 +8540,20 @@ static void intel_set_config_restore_state(struct drm_device *dev,
8540} 8540}
8541 8541
8542static bool 8542static bool
8543is_crtc_connector_off(struct drm_crtc *crtc, struct drm_connector *connectors, 8543is_crtc_connector_off(struct drm_mode_set *set)
8544 int num_connectors)
8545{ 8544{
8546 int i; 8545 int i;
8547 8546
8548 for (i = 0; i < num_connectors; i++) 8547 if (set->num_connectors == 0)
8549 if (connectors[i].encoder && 8548 return false;
8550 connectors[i].encoder->crtc == crtc && 8549
8551 connectors[i].dpms != DRM_MODE_DPMS_ON) 8550 if (WARN_ON(set->connectors == NULL))
8551 return false;
8552
8553 for (i = 0; i < set->num_connectors; i++)
8554 if (set->connectors[i]->encoder &&
8555 set->connectors[i]->encoder->crtc == set->crtc &&
8556 set->connectors[i]->dpms != DRM_MODE_DPMS_ON)
8552 return true; 8557 return true;
8553 8558
8554 return false; 8559 return false;
@@ -8561,10 +8566,8 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
8561 8566
8562 /* We should be able to check here if the fb has the same properties 8567 /* We should be able to check here if the fb has the same properties
8563 * and then just flip_or_move it */ 8568 * and then just flip_or_move it */
8564 if (set->connectors != NULL && 8569 if (is_crtc_connector_off(set)) {
8565 is_crtc_connector_off(set->crtc, *set->connectors, 8570 config->mode_changed = true;
8566 set->num_connectors)) {
8567 config->mode_changed = true;
8568 } else if (set->crtc->fb != set->fb) { 8571 } else if (set->crtc->fb != set->fb) {
8569 /* If we have no fb then treat it as a full mode set */ 8572 /* If we have no fb then treat it as a full mode set */
8570 if (set->crtc->fb == NULL) { 8573 if (set->crtc->fb == NULL) {