*/
 void drm_modeset_lock_all(struct drm_device *dev)
 {
+       struct drm_crtc *crtc;
+
        mutex_lock(&dev->mode_config.mutex);
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+               mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex);
 }
 EXPORT_SYMBOL(drm_modeset_lock_all);
 
  */
 void drm_modeset_unlock_all(struct drm_device *dev)
 {
+       struct drm_crtc *crtc;
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+               mutex_unlock(&crtc->mutex);
+
        mutex_unlock(&dev->mode_config.mutex);
 }
 EXPORT_SYMBOL(drm_modeset_unlock_all);
        crtc->invert_dimensions = false;
 
        drm_modeset_lock_all(dev);
+       mutex_init(&crtc->mutex);
+       mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex);
 
        ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
        if (ret)
 
        struct drm_device *dev;
        struct list_head head;
 
+       /**
+        * crtc mutex
+        *
+        * This provides a read lock for the overall crtc state (mode, dpms
+        * state, ...) and a write lock for everything which can be update
+        * without a full modeset (fb, cursor data, ...)
+        */
+       struct mutex mutex;
+
        struct drm_mode_object base;
 
        /* framebuffer the connector is currently bound to */