Blob Blame History Raw
From: Daniel Vetter <daniel.vetter@ffwll.ch>
Date: Tue, 17 Oct 2017 17:27:14 +0200
Subject: drm/atomic-helper: check that drivers call drm_crtc_vblank_off
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Git-commit: 84014b0a39eef6df4a26f8afabf2b50bd376d515
Patch-mainline: v4.15-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

At least when they have vblank support they need to call this, or the
vblank core will happily call into their crtc->enable_vblank callback
even when the crtc is off. Which leads to a boom when the clocks are
off on most hardware (besides the inevitable confusion in the
book-keeping).

The consistency checks in drm_vblank.c will then make sure that
vblank_off/on calls are balanced, and if drivers forget to re-enable
it all the commits will stall, so I think we're covered.

It'd be nice to be able to place this check outside of commit helpers,
but tha's not really possible (due to nonblocking commits and all
that). Placing it into atomic helpers should at least cover most
drivers.

Also note that vblank support is still optional (for virtual drivers,
which tend to not have this), check for that.

v2: Fixup the handling for vblank_put (Rob).

Cc: Rob Clark <robdclark@gmail.com>
Tested-by: Rob Clark <robdclark@gmail.com>
Cc: Ville Syrj채l채 <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrj채l채 <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20171017152714.6849-1-daniel.vetter@ffwll.ch

Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/drm_atomic_helper.c |    9 +++++++++
 1 file changed, 9 insertions(+)

--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -860,6 +860,7 @@ disable_outputs(struct drm_device *dev,
 
 	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
 		const struct drm_crtc_helper_funcs *funcs;
+		int ret;
 
 		/* Shut down everything that needs a full modeset. */
 		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
@@ -883,6 +884,14 @@ disable_outputs(struct drm_device *dev,
 			funcs->disable(crtc);
 		else
 			funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+
+		if (!(dev->irq_enabled && dev->num_crtcs))
+			continue;
+
+		ret = drm_crtc_vblank_get(crtc);
+		WARN_ONCE(ret != -EINVAL, "driver forgot to call drm_crtc_vblank_off()\n");
+		if (ret == 0)
+			drm_crtc_vblank_put(crtc);
 	}
 }