Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/external/bsd/drm2/dist drm: New mechanism to suspend ioc...



details:   https://anonhg.NetBSD.org/src/rev/fbd4a0ea533d
branches:  trunk
changeset: 371868:fbd4a0ea533d
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sat Oct 15 15:19:28 2022 +0000

description:
drm: New mechanism to suspend ioctls during system suspend.

drm drivers must opt into this by calling drm_suspend_ioctl in their
driver suspend routine, and drm_resume_ioctl in their driver resume
routine.

This is a stop-gap measure -- it would be better to fill in the
pm_runtime_* API with new pmf(9) hooks to acquire/release references
to devices for coordinating with suspend/resume, but getting the
details right is tricky, and this stop-gap is enough to get i915
suspend/resume to work reliably on my Kaby Lake laptop.  Rather than
wait until I've got all the details right, let's just go with this
stop-gap for now.

diffstat:

 sys/external/bsd/drm2/dist/drm/drm_drv.c            |  23 +++++++-
 sys/external/bsd/drm2/dist/drm/drm_ioctl.c          |  63 ++++++++++++++++++++-
 sys/external/bsd/drm2/dist/include/drm/drm_device.h |   7 ++-
 sys/external/bsd/drm2/dist/include/drm/drm_ioctl.h  |   4 +-
 4 files changed, 91 insertions(+), 6 deletions(-)

diffs (216 lines):

diff -r c87a0522a349 -r fbd4a0ea533d sys/external/bsd/drm2/dist/drm/drm_drv.c
--- a/sys/external/bsd/drm2/dist/drm/drm_drv.c  Sat Oct 15 14:54:21 2022 +0000
+++ b/sys/external/bsd/drm2/dist/drm/drm_drv.c  Sat Oct 15 15:19:28 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: drm_drv.c,v 1.23 2022/07/17 14:11:18 riastradh Exp $   */
+/*     $NetBSD: drm_drv.c,v 1.24 2022/10/15 15:19:28 riastradh Exp $   */
 
 /*
  * Created: Fri Jan 19 10:48:35 2001 by faith%acm.org@localhost
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.23 2022/07/17 14:11:18 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.24 2022/10/15 15:19:28 riastradh Exp $");
 
 #include <linux/debugfs.h>
 #include <linux/fs.h>
@@ -695,6 +695,12 @@
        mutex_init(&dev->filelist_mutex);
        mutex_init(&dev->clientlist_mutex);
        mutex_init(&dev->master_mutex);
+#ifdef __NetBSD__
+       mutex_init(&dev->suspend_lock);
+       DRM_INIT_WAITQUEUE(&dev->suspend_cv, "drmsusp");
+       dev->active_ioctls = 0;
+       dev->suspender = NULL;
+#endif
 
        dev->sc_monitor_hotplug.smpsw_name = PSWITCH_HK_DISPLAY_CYCLE;
        dev->sc_monitor_hotplug.smpsw_type = PSWITCH_TYPE_HOTKEY;
@@ -757,6 +763,12 @@
 #ifndef __NetBSD__             /* XXX drm sysfs */
        put_device(dev->dev);
 #endif
+#ifdef __NetBSD__
+       KASSERT(dev->suspender == NULL);
+       KASSERT(dev->active_ioctls == 0);
+       DRM_DESTROY_WAITQUEUE(&dev->suspend_cv);
+       mutex_destroy(&dev->suspend_lock);
+#endif
        mutex_destroy(&dev->master_mutex);
        mutex_destroy(&dev->clientlist_mutex);
        mutex_destroy(&dev->filelist_mutex);
@@ -844,6 +856,13 @@
        put_device(dev->dev);
 #endif
 
+#ifdef __NetBSD__
+       KASSERT(dev->suspender == NULL);
+       KASSERT(dev->active_ioctls == 0);
+       DRM_DESTROY_WAITQUEUE(&dev->suspend_cv);
+       mutex_destroy(&dev->suspend_lock);
+#endif
+
        mutex_destroy(&dev->master_mutex);
        mutex_destroy(&dev->clientlist_mutex);
        mutex_destroy(&dev->filelist_mutex);
diff -r c87a0522a349 -r fbd4a0ea533d sys/external/bsd/drm2/dist/drm/drm_ioctl.c
--- a/sys/external/bsd/drm2/dist/drm/drm_ioctl.c        Sat Oct 15 14:54:21 2022 +0000
+++ b/sys/external/bsd/drm2/dist/drm/drm_ioctl.c        Sat Oct 15 15:19:28 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: drm_ioctl.c,v 1.23 2022/08/27 21:24:15 riastradh Exp $ */
+/*     $NetBSD: drm_ioctl.c,v 1.24 2022/10/15 15:19:28 riastradh Exp $ */
 
 /*
  * Created: Fri Jan  8 09:01:26 1999 by faith%valinux.com@localhost
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_ioctl.c,v 1.23 2022/08/27 21:24:15 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_ioctl.c,v 1.24 2022/10/15 15:19:28 riastradh Exp $");
 
 #include <linux/export.h>
 #include <linux/nospec.h>
@@ -739,6 +739,58 @@
 
 #define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
 
+#ifdef __NetBSD__
+/* ioctl suspend/resume */
+
+static void
+drm_ioctl_enter(struct drm_device *dev)
+{
+       int ret __diagused;
+
+       mutex_lock(&dev->suspend_lock);
+       DRM_WAIT_NOINTR_UNTIL(ret, &dev->suspend_cv, &dev->suspend_lock,
+           dev->suspender == NULL);
+       KASSERTMSG(ret == 0, "error=%d", -ret);
+       dev->active_ioctls++;
+       mutex_unlock(&dev->suspend_lock);
+}
+
+static void
+drm_ioctl_exit(struct drm_device *dev)
+{
+
+       mutex_lock(&dev->suspend_lock);
+       KASSERT(dev->suspender == NULL);
+       if (--dev->active_ioctls == 0)
+               DRM_WAKEUP_ALL(&dev->suspend_cv, &dev->suspend_lock);
+       mutex_unlock(&dev->suspend_lock);
+}
+
+void
+drm_suspend_ioctl(struct drm_device *dev)
+{
+       int ret;
+
+       mutex_lock(&dev->suspend_lock);
+       DRM_WAIT_NOINTR_UNTIL(ret, &dev->suspend_cv, &dev->suspend_lock,
+           dev->suspender == NULL && dev->active_ioctls == 0);
+       dev->suspender = curlwp;
+       mutex_unlock(&dev->suspend_lock);
+}
+
+void
+drm_resume_ioctl(struct drm_device *dev)
+{
+
+       mutex_lock(&dev->suspend_lock);
+       KASSERT(dev->suspender);
+       KASSERT(dev->active_ioctls == 0);
+       dev->suspender = NULL;
+       DRM_WAKEUP_ALL(&dev->suspend_cv, &dev->suspend_lock);
+       mutex_unlock(&dev->suspend_lock);
+}
+#endif
+
 /**
  * DOC: driver specific ioctls
  *
@@ -805,6 +857,8 @@
        if (unlikely(retcode))
                return retcode;
 
+       drm_ioctl_enter(dev);
+
        /* Enforce sane locking for modern driver ioctls. */
        if (likely(!drm_core_check_feature(dev, DRIVER_LEGACY)) ||
            (flags & DRM_UNLOCKED))
@@ -814,6 +868,9 @@
                retcode = func(dev, kdata, file_priv);
                mutex_unlock(&drm_global_mutex);
        }
+
+       drm_ioctl_exit(dev);
+
        return retcode;
 }
 EXPORT_SYMBOL(drm_ioctl_kernel);
@@ -900,6 +957,7 @@
                data0 = buf;
        }
 
+       drm_ioctl_enter(dev);
        if ((drm_core_check_feature(dev, DRIVER_MODESET) && is_driver_ioctl) ||
            ISSET(ioctl->flags, DRM_UNLOCKED)) {
                /* XXX errno Linux->NetBSD */
@@ -910,6 +968,7 @@
                error = -(*ioctl->func)(dev, data0, file);
                mutex_unlock(&drm_global_mutex);
        }
+       drm_ioctl_exit(dev);
 
        /* If we used a temporary buffer, copy it back out.  */
        if (data != data0)
diff -r c87a0522a349 -r fbd4a0ea533d sys/external/bsd/drm2/dist/include/drm/drm_device.h
--- a/sys/external/bsd/drm2/dist/include/drm/drm_device.h       Sat Oct 15 14:54:21 2022 +0000
+++ b/sys/external/bsd/drm2/dist/include/drm/drm_device.h       Sat Oct 15 15:19:28 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: drm_device.h,v 1.10 2021/12/22 12:05:24 riastradh Exp $        */
+/*     $NetBSD: drm_device.h,v 1.11 2022/10/15 15:19:28 riastradh Exp $        */
 
 #ifndef _DRM_DEVICE_H_
 #define _DRM_DEVICE_H_
@@ -12,6 +12,7 @@
 #include <drm/drm_mode_config.h>
 
 #ifdef __NetBSD__
+#include <drm/drm_wait_netbsd.h>
 #include <dev/sysmon/sysmonvar.h>
 #endif
 
@@ -332,6 +333,10 @@
 
 #ifdef __NetBSD__
        struct sysmon_pswitch sc_monitor_hotplug;
+       struct mutex suspend_lock;
+       drm_waitqueue_t suspend_cv;
+       uint64_t active_ioctls;
+       struct lwp *suspender;
 #endif
 
        /* Everything below here is for legacy driver, never use! */
diff -r c87a0522a349 -r fbd4a0ea533d sys/external/bsd/drm2/dist/include/drm/drm_ioctl.h
--- a/sys/external/bsd/drm2/dist/include/drm/drm_ioctl.h        Sat Oct 15 14:54:21 2022 +0000
+++ b/sys/external/bsd/drm2/dist/include/drm/drm_ioctl.h        Sat Oct 15 15:19:28 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: drm_ioctl.h,v 1.4 2021/12/19 01:56:08 riastradh Exp $  */
+/*     $NetBSD: drm_ioctl.h,v 1.5 2022/10/15 15:19:28 riastradh Exp $  */
 
 /*
  * Internal Header for the Direct Rendering Manager
@@ -178,6 +178,8 @@
 int drm_ioctl_permit(u32 flags, struct drm_file *file_priv);
 #ifdef __NetBSD__
 int drm_ioctl(struct file *, unsigned long, void *);
+void drm_suspend_ioctl(struct drm_device *);
+void drm_resume_ioctl(struct drm_device *);
 #else
 long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 #endif



Home | Main Index | Thread Index | Old Index