[PATCH 1/2] drm/crtc-helper: Fixup error handling in drm_helper_crtc_mode_set

Daniel Vetter daniel.vetter at ffwll.ch
Thu Jul 2 07:00:26 PDT 2015


In

commit 9f658b7b62e7aefc1ee067136126eca3f58cabfd
Author: Daniel Stone <daniels at collabora.com>
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.

v4: Argh, I removed Daniel's fix by accident completely. Reinit the
state properly, even when we allocate it afresh.

Cc: Daniel Stone <daniels at collabora.com>
CC: Sean Paul <seanpaul at chromium.org>
Cc: John Hunter <zhaojunwang at pku.edu.cn>
Reported-by: John Hunter <zhaojunwang at pku.edu.cn>
Signed-off-by: Daniel Vetter <daniel.vetter at intel.com>
---
 drivers/gpu/drm/drm_crtc_helper.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 393114df88a3..280e8581c704 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -927,16 +927,17 @@ 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 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)
+		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;
 	ret = drm_atomic_set_mode_for_crtc(crtc_state, mode);
@@ -957,11 +958,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.1.4



More information about the dri-devel mailing list