drm/i915: Disable all crtcs during driver unload, v2.
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Thu, 15 Dec 2016 14:29:44 +0000 (15:29 +0100)
committerMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Wed, 1 Feb 2017 21:04:37 +0000 (22:04 +0100)
We may keep the crtc's enabled when userspace unsets all framebuffers but
keeps the crtc active. This exposes a WARN in fbc_global disable, and
a lot of bugs in our hardware readout code. Solve this by disabling
all crtc's for now.

Changes since v1:
- Use lock_all_ctx instead of lock_all.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1481812185-19098-4-git-send-email-maarten.lankhorst@linux.intel.com
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_drv.c

index 0e99cb22362cf90d5fd6d22766d3f5b98f786f57..0667f480df9786dc1b05ea19f8e2126ccd55cfa2 100644 (file)
@@ -43,6 +43,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/i915_drm.h>
 
 #include "i915_drv.h"
@@ -1307,6 +1308,8 @@ void i915_driver_unload(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct pci_dev *pdev = dev_priv->drm.pdev;
+       struct drm_modeset_acquire_ctx ctx;
+       int ret;
 
        intel_fbdev_fini(dev);
 
@@ -1315,6 +1318,24 @@ void i915_driver_unload(struct drm_device *dev)
 
        intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 
+       drm_modeset_acquire_init(&ctx, 0);
+       while (1) {
+               ret = drm_modeset_lock_all_ctx(dev, &ctx);
+               if (!ret)
+                       ret = drm_atomic_helper_disable_all(dev, &ctx);
+
+               if (ret != -EDEADLK)
+                       break;
+
+               drm_modeset_backoff(&ctx);
+       }
+
+       if (ret)
+               DRM_ERROR("Disabling all crtc's during unload failed with %i\n", ret);
+
+       drm_modeset_drop_locks(&ctx);
+       drm_modeset_acquire_fini(&ctx);
+
        i915_driver_unregister(dev_priv);
 
        drm_vblank_cleanup(dev);