From ce14ec20a1ffcd356f578036617d657be8429c00 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 2 Jul 2015 15:16:39 +0200 Subject: [PATCH] drm/crtc-helper: Fixup error handling in drm_helper_crtc_mode_set In commit 9f658b7b62e7aefc1ee067136126eca3f58cabfd Author: Daniel Stone Date: Fri May 22 13:34:45 2015 +0100 drm/crtc_helper: Replace open-coded CRTC state helpers error handling code was broken, resulting in the first path not being checked correctly. Fix this by using the same pattern as in the transitional plane helper function drm_plane_helper_update. v2: Simplify the cleanup code while at it too. v3: After some debugging with John we realized that the above patch from Daniel also accidentally removed the if (crtc_state) check. This is legal when transitioning to atomic, when the initial state reset isn't all wired up yet properly. Reinstate that check to fix the bug John has hit. Cc: Daniel Stone CC: Sean Paul Cc: John Hunter Signed-off-by: Daniel Vetter Reviewed-by: Daniel Stone Reported-and-tested-by: John Hunter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc_helper.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 393114df88a3..93104f3555f5 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -927,15 +927,13 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mod if (crtc->funcs->atomic_duplicate_state) crtc_state = crtc->funcs->atomic_duplicate_state(crtc); - else { + else if (crtc->state) + crtc_state = drm_atomic_helper_crtc_duplicate_state(crtc); + else crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); - if (!crtc_state) - return -ENOMEM; - if (crtc->state) - __drm_atomic_helper_crtc_duplicate_state(crtc, crtc_state); - else - crtc_state->crtc = crtc; - } + + if (!crtc_state) + return -ENOMEM; crtc_state->planes_changed = true; crtc_state->mode_changed = true; @@ -957,11 +955,11 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mod ret = drm_helper_crtc_mode_set_base(crtc, x, y, old_fb); out: - if (crtc->funcs->atomic_destroy_state) - crtc->funcs->atomic_destroy_state(crtc, crtc_state); - else { - __drm_atomic_helper_crtc_destroy_state(crtc, crtc_state); - kfree(crtc_state); + if (crtc_state) { + if (crtc->funcs->atomic_destroy_state) + crtc->funcs->atomic_destroy_state(crtc, crtc_state); + else + drm_atomic_helper_crtc_destroy_state(crtc, crtc_state); } return ret; -- 2.39.5