diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2016-05-06 13:47:45 +0200 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-05-18 10:42:01 +0200 |
commit | e2d800a3ce1b16a9c25fc6ca91f26df5509ca11d (patch) | |
tree | 61cab4ecdf3ca2ebd1761ba0c8f446a99de7afb0 /drivers/gpu/drm/drm_atomic.c | |
parent | drm/fb_helper: Fix references to dev->mode_config.num_connector (diff) | |
download | linux-e2d800a3ce1b16a9c25fc6ca91f26df5509ca11d.tar.xz linux-e2d800a3ce1b16a9c25fc6ca91f26df5509ca11d.zip |
drm: Avoid connector reference imbalance on error path
Whilst looking at the fallout from using connector references for
atomic, I noticed that there is an early return buried in
drm_atomic_set_crtc_for_connector() that if hit could cause us to leak a
reference on the connector.
Fixes: d2307dea14 (drm/atomic: use connector references (v3))
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Stone <daniels@collabora.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Airlie <airlied@redhat.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1462535265-13058-1-git-send-email-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/drm_atomic.c')
-rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 86e89db02ed7..3ff1ed7b33db 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1160,14 +1160,18 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, { struct drm_crtc_state *crtc_state; - if (crtc) - drm_connector_reference(conn_state->connector); - if (conn_state->crtc && conn_state->crtc != crtc) { + if (conn_state->crtc == crtc) + return 0; + + if (conn_state->crtc) { crtc_state = drm_atomic_get_existing_crtc_state(conn_state->state, conn_state->crtc); crtc_state->connector_mask &= ~(1 << drm_connector_index(conn_state->connector)); + + drm_connector_unreference(conn_state->connector); + conn_state->crtc = NULL; } if (crtc) { @@ -1177,18 +1181,16 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, crtc_state->connector_mask |= 1 << drm_connector_index(conn_state->connector); - } - if (conn_state->crtc) - drm_connector_unreference(conn_state->connector); - conn_state->crtc = crtc; + drm_connector_reference(conn_state->connector); + conn_state->crtc = crtc; - if (crtc) DRM_DEBUG_ATOMIC("Link connector state %p to [CRTC:%d:%s]\n", conn_state, crtc->base.id, crtc->name); - else + } else { DRM_DEBUG_ATOMIC("Link connector state %p to [NOCRTC]\n", conn_state); + } return 0; } |