[PATCH 12/12] [RFC] drm/crtc-helper: Enforce sane vblank counter semantics

Daniel Vetter
2014-05-14T18:51:52Z

It literally took us years in i915 to track down all the vblank
bogosity, which means that userspace has now code to deal with random
crap like stuck vblank waits, needless counter wraps and other
hilarity.

To make sure that all drivers are at least somewhat sane enforce
minimal standards in the crtc helpers. Note that this is not perfect
since for intermediate levels it's unclear whether the vblank will
keep on running. Modern userspace is advised to just never use those.

Totatlly untested.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
drivers/gpu/drm/drm_crtc_helper.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index df281b54db01..64d8797cd172 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -167,6 +167,8 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev)
else
(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
crtc->primary->fb = NULL;
+
+ drm_crtc_vblank_off(crtc->dev, crtc);
}
}
}
@@ -323,6 +325,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,

crtc_funcs->prepare(crtc);

+ drm_crtc_vblank_off(dev, crtc);
+
/* Set up the DPLL and any encoders state that needs to adjust or depend
* on the DPLL.
*/
@@ -349,6 +353,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
crtc_funcs->commit(crtc);

+ drm_crtc_vblank_on(dev, crtc);
+
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {

if (encoder->crtc != crtc)
@@ -767,6 +773,9 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
if (crtc_funcs->dpms)
(*crtc_funcs->dpms) (crtc,
drm_helper_choose_crtc_dpms(crtc));
+
+ if (mode == DRM_MODE_DPMS_ON)
+ drm_crtc_vblank_on(crtc->dev, crtc);
}
if (encoder)
drm_helper_encoder_dpms(encoder, encoder_dpms);
@@ -781,6 +790,9 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
if (crtc_funcs->dpms)
(*crtc_funcs->dpms) (crtc,
drm_helper_choose_crtc_dpms(crtc));
+
+ if (mode == DRM_MODE_DPMS_OFF)
+ drm_crtc_vblank_off(crtc->dev, crtc);
}
}

--
1.8.3.1