drm: Check output polling initialized before disabling
authorjsg <jsg@openbsd.org>
Mon, 15 Apr 2024 01:46:03 +0000 (01:46 +0000)
committerjsg <jsg@openbsd.org>
Mon, 15 Apr 2024 01:46:03 +0000 (01:46 +0000)
From Shradha Gupta
3d1b47e3a935abd4f258a945db87e7267ff4079c in linux-6.6.y/6.6.27
5abffb66d12bcac84bf7b66389c571b8bb6e82bd in mainline linux

sys/dev/pci/drm/drm_modeset_helper.c
sys/dev/pci/drm/drm_probe_helper.c

index f858dfe..2c58202 100644 (file)
@@ -193,13 +193,22 @@ int drm_mode_config_helper_suspend(struct drm_device *dev)
 
        if (!dev)
                return 0;
+       /*
+        * Don't disable polling if it was never initialized
+        */
+       if (dev->mode_config.poll_enabled)
+               drm_kms_helper_poll_disable(dev);
 
-       drm_kms_helper_poll_disable(dev);
        drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 1);
        state = drm_atomic_helper_suspend(dev);
        if (IS_ERR(state)) {
                drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
-               drm_kms_helper_poll_enable(dev);
+               /*
+                * Don't enable polling if it was never initialized
+                */
+               if (dev->mode_config.poll_enabled)
+                       drm_kms_helper_poll_enable(dev);
+
                return PTR_ERR(state);
        }
 
@@ -239,7 +248,11 @@ int drm_mode_config_helper_resume(struct drm_device *dev)
        dev->mode_config.suspend_state = NULL;
 
        drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
-       drm_kms_helper_poll_enable(dev);
+       /*
+        * Don't enable polling if it is not initialized
+        */
+       if (dev->mode_config.poll_enabled)
+               drm_kms_helper_poll_enable(dev);
 
        return ret;
 }
index 169df04..fd7deaa 100644 (file)
@@ -293,14 +293,17 @@ static void reschedule_output_poll_work(struct drm_device *dev)
  * Drivers can call this helper from their device resume implementation. It is
  * not an error to call this even when output polling isn't enabled.
  *
+ * If device polling was never initialized before, this call will trigger a
+ * warning and return.
+ *
  * Note that calls to enable and disable polling must be strictly ordered, which
  * is automatically the case when they're only call from suspend/resume
  * callbacks.
  */
 void drm_kms_helper_poll_enable(struct drm_device *dev)
 {
-       if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll ||
-           dev->mode_config.poll_running)
+       if (drm_WARN_ON_ONCE(dev, !dev->mode_config.poll_enabled) ||
+           !drm_kms_helper_poll || dev->mode_config.poll_running)
                return;
 
        if (drm_kms_helper_enable_hpd(dev) ||
@@ -881,12 +884,18 @@ EXPORT_SYMBOL(drm_kms_helper_is_poll_worker);
  * not an error to call this even when output polling isn't enabled or already
  * disabled. Polling is re-enabled by calling drm_kms_helper_poll_enable().
  *
+ * If however, the polling was never initialized, this call will trigger a
+ * warning and return
+ *
  * Note that calls to enable and disable polling must be strictly ordered, which
  * is automatically the case when they're only call from suspend/resume
  * callbacks.
  */
 void drm_kms_helper_poll_disable(struct drm_device *dev)
 {
+       if (drm_WARN_ON(dev, !dev->mode_config.poll_enabled))
+               return;
+
        if (dev->mode_config.poll_running)
                drm_kms_helper_disable_hpd(dev);