Index | Thread | Search

From:
Vitaliy Makkoveev <mvs@openbsd.org>
Subject:
mp-safe drm*_filtops
To:
tech@openbsd.org
Date:
Fri, 18 Jul 2025 23:31:05 +0300

Download raw body.

Thread
The resurrection my old diff. No reason for X to stuck in kernel lock
while polling.

The `event_lock' mutex(9) is already protects `event_list' checked by
filt_drmread(), so use it to protect the `drmread_filtops' too.

The filt_drmkms() doesn't touch any data and could be easily converted
to always return 1, so the lock is only required for `drm_filtops'.
Introduce the new `note_mtx' mutex(9) for that purpose.

I have no radeondrm(4), so tested with inteldrm(4) only. Previous time I
had successful reports from people with radeondrm(4) too.

Index: sys/dev/pci/drm/drm_connector.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_connector.c,v
retrieving revision 1.15
diff -u -p -r1.15 drm_connector.c
--- sys/dev/pci/drm/drm_connector.c	24 Mar 2025 02:33:30 -0000	1.15
+++ sys/dev/pci/drm/drm_connector.c	18 Jul 2025 20:20:49 -0000
@@ -3093,7 +3093,7 @@ int drm_connector_set_obj_prop(struct dr
 	} else if (property == connector->backlight_property) {
 		connector->backlight_device->props.brightness = value;
 		backlight_schedule_update_status(connector->backlight_device);
-		knote_locked(&connector->dev->note, NOTE_CHANGE);
+		knote(&connector->dev->note, NOTE_CHANGE);
 		ret = 0;
 #endif
 	} else if (connector->funcs->set_property)
Index: sys/dev/pci/drm/drm_drv.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_drv.c,v
retrieving revision 1.203
diff -u -p -r1.203 drm_drv.c
--- sys/dev/pci/drm/drm_drv.c	2 Jul 2025 12:19:26 -0000	1.203
+++ sys/dev/pci/drm/drm_drv.c	18 Jul 2025 20:20:49 -0000
@@ -1362,6 +1362,9 @@ drm_attach(struct device *parent, struct
 	dev->dev_private = parent;
 	dev->driver = da->driver;
 
+	mtx_init(&dev->note_mtx, IPL_MPFLOOR);
+	klist_init_mutex(&dev->note, &dev->note_mtx);
+
 	INIT_LIST_HEAD(&dev->managed.resources);
 	mtx_init(&dev->managed.lock, IPL_TTY);
 
@@ -1640,58 +1643,108 @@ void
 filt_drmdetach(struct knote *kn)
 {
 	struct drm_device *dev = kn->kn_hook;
-	int s;
 
-	s = spltty();
-	klist_remove_locked(&dev->note, kn);
-	splx(s);
+	klist_remove(&dev->note, kn);
 }
 
 int
 filt_drmkms(struct knote *kn, long hint)
 {
+	struct drm_device *dev = kn->kn_hook;
+
+	MUTEX_ASSERT_LOCKED(&dev->note_mtx);
+
 	if (kn->kn_sfflags & hint)
 		kn->kn_fflags |= hint;
 	return (kn->kn_fflags != 0);
 }
 
+int
+filt_drmmodify(struct kevent *kev, struct knote *kn)
+{
+	struct drm_device *dev = kn->kn_hook;
+	int active;
+
+	mtx_enter(&dev->note_mtx);
+	active = knote_modify(kev, kn);
+	mtx_leave(&dev->note_mtx);
+
+	return (active);
+}
+
+int
+filt_drmprocess(struct knote *kn, struct kevent *kev)
+{
+	struct drm_device *dev = kn->kn_hook;
+	int active;
+
+	mtx_enter(&dev->note_mtx);
+	active = knote_process(kn, kev);
+	mtx_leave(&dev->note_mtx);
+
+	return (active);
+}
+
 void
 filt_drmreaddetach(struct knote *kn)
 {
 	struct drm_file		*file_priv = kn->kn_hook;
-	int s;
 
-	s = spltty();
-	klist_remove_locked(&file_priv->rsel.si_note, kn);
-	splx(s);
+	klist_remove(&file_priv->rklist, kn);
 }
 
 int
 filt_drmread(struct knote *kn, long hint)
 {
 	struct drm_file		*file_priv = kn->kn_hook;
-	int			 val = 0;
 
-	if ((hint & NOTE_SUBMIT) == 0)
-		mtx_enter(&file_priv->minor->dev->event_lock);
-	val = !list_empty(&file_priv->event_list);
-	if ((hint & NOTE_SUBMIT) == 0)
-		mtx_leave(&file_priv->minor->dev->event_lock);
-	return (val);
+	MUTEX_ASSERT_LOCKED(&file_priv->minor->dev->event_lock);
+
+	return !(list_empty(&file_priv->event_list));
+}
+
+int
+filt_drmreadmodify(struct kevent *kev, struct knote *kn)
+{
+	struct drm_file		*file_priv = kn->kn_hook;
+	int			 active;
+
+	mtx_enter(&file_priv->minor->dev->event_lock);
+	active = knote_modify(kev, kn);
+	mtx_leave(&file_priv->minor->dev->event_lock);
+
+	return (active);
+}
+
+int
+filt_drmreadprocess(struct knote *kn, struct kevent *kev)
+{
+	struct drm_file		*file_priv = kn->kn_hook;
+	int			 active;
+
+	mtx_enter(&file_priv->minor->dev->event_lock);
+	active = knote_process(kn, kev);
+	mtx_leave(&file_priv->minor->dev->event_lock);
+
+	return (active);
 }
 
 const struct filterops drm_filtops = {
-	.f_flags	= FILTEROP_ISFD,
+	.f_flags	= FILTEROP_ISFD | FILTEROP_MPSAFE,
 	.f_attach	= NULL,
 	.f_detach	= filt_drmdetach,
 	.f_event	= filt_drmkms,
+	.f_modify	= filt_drmmodify,
+	.f_process	= filt_drmprocess,
 };
 
 const struct filterops drmread_filtops = {
-	.f_flags	= FILTEROP_ISFD,
+	.f_flags	= FILTEROP_ISFD | FILTEROP_MPSAFE,
 	.f_attach	= NULL,
 	.f_detach	= filt_drmreaddetach,
 	.f_event	= filt_drmread,
+	.f_modify	= filt_drmreadmodify,
+	.f_process	= filt_drmreadprocess,
 };
 
 int
@@ -1699,7 +1752,6 @@ drmkqfilter(dev_t kdev, struct knote *kn
 {
 	struct drm_device	*dev = NULL;
 	struct drm_file		*file_priv = NULL;
-	int			 s;
 
 	dev = drm_get_device_from_kdev(kdev);
 	if (dev == NULL || dev->dev_private == NULL)
@@ -1716,17 +1768,13 @@ drmkqfilter(dev_t kdev, struct knote *kn
 		kn->kn_fop = &drmread_filtops;
 		kn->kn_hook = file_priv;
 
-		s = spltty();
-		klist_insert_locked(&file_priv->rsel.si_note, kn);
-		splx(s);
+		klist_insert(&file_priv->rklist, kn);
 		break;
 	case EVFILT_DEVICE:
 		kn->kn_fop = &drm_filtops;
 		kn->kn_hook = dev;
 
-		s = spltty();
-		klist_insert_locked(&dev->note, kn);
-		splx(s);
+		klist_insert(&dev->note, kn);
 		break;
 	default:
 		return (EINVAL);
Index: sys/dev/pci/drm/drm_file.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_file.c,v
retrieving revision 1.15
diff -u -p -r1.15 drm_file.c
--- sys/dev/pci/drm/drm_file.c	12 May 2025 08:02:35 -0000	1.15
+++ sys/dev/pci/drm/drm_file.c	18 Jul 2025 20:20:49 -0000
@@ -160,6 +160,8 @@ struct drm_file *drm_file_alloc(struct d
 	mtx_init(&file->master_lookup_lock, IPL_NONE);
 	rw_init(&file->event_read_lock, "evread");
 
+	klist_init_mutex(&file->rklist, &dev->event_lock);
+
 	if (drm_core_check_feature(dev, DRIVER_GEM))
 		drm_gem_open(dev, file);
 
@@ -244,6 +246,9 @@ void drm_file_free(struct drm_file *file
 
 	drm_events_release(file);
 
+	klist_invalidate(&file->rklist);
+	klist_free(&file->rklist);
+
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 		drm_fb_release(file);
 		drm_property_destroy_user_blobs(dev, file);
@@ -789,7 +794,7 @@ static void drm_send_event_helper(struct
 	wake_up_interruptible_poll(&e->file_priv->event_wait,
 		EPOLLIN | EPOLLRDNORM);
 #ifdef __OpenBSD__
-	selwakeup(&e->file_priv->rsel);
+	knote_locked(&e->file_priv->rklist, NOTE_CHANGE);
 #endif
 }
 
Index: sys/dev/pci/drm/drm_linux.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_linux.c,v
retrieving revision 1.126
diff -u -p -r1.126 drm_linux.c
--- sys/dev/pci/drm/drm_linux.c	13 Jun 2025 07:01:37 -0000	1.126
+++ sys/dev/pci/drm/drm_linux.c	18 Jul 2025 20:20:49 -0000
@@ -1669,13 +1669,13 @@ dev_get_drvdata(struct device *dev)
 void
 drm_sysfs_hotplug_event(struct drm_device *dev)
 {
-	knote_locked(&dev->note, NOTE_CHANGE);
+	knote(&dev->note, NOTE_CHANGE);
 }
 
 void
 drm_sysfs_connector_hotplug_event(struct drm_connector *connector)
 {
-	knote_locked(&connector->dev->note, NOTE_CHANGE);
+	knote(&connector->dev->note, NOTE_CHANGE);
 }
 
 void
Index: sys/dev/pci/drm/drm_mode_object.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_mode_object.c,v
retrieving revision 1.9
diff -u -p -r1.9 drm_mode_object.c
--- sys/dev/pci/drm/drm_mode_object.c	7 Feb 2025 03:03:08 -0000	1.9
+++ sys/dev/pci/drm/drm_mode_object.c	18 Jul 2025 20:20:49 -0000
@@ -564,7 +564,7 @@ retry:
 		struct drm_connector *connector = obj_to_connector(obj);
 		connector->backlight_device->props.brightness = prop_value;
 		backlight_schedule_update_status(connector->backlight_device);
-		knote_locked(&connector->dev->note, NOTE_CHANGE);
+		knote(&connector->dev->note, NOTE_CHANGE);
 		ret = 0;
 #endif
 	} else {
Index: sys/dev/pci/drm/amd/amdgpu/amdgpu_drv.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/amd/amdgpu/amdgpu_drv.c,v
retrieving revision 1.63
diff -u -p -r1.63 amdgpu_drv.c
--- sys/dev/pci/drm/amd/amdgpu/amdgpu_drv.c	5 Jul 2025 23:44:49 -0000	1.63
+++ sys/dev/pci/drm/amd/amdgpu/amdgpu_drv.c	18 Jul 2025 20:20:49 -0000
@@ -3574,7 +3574,7 @@ amdgpu_wsioctl(void *v, u_long cmd, cadd
 		case WSDISPLAYIO_PARAM_BRIGHTNESS:
 			bd->props.brightness = dp->curval;
 			backlight_update_status(bd);
-			knote_locked(&adev->ddev.note, NOTE_CHANGE);
+			knote(&adev->ddev.note, NOTE_CHANGE);
 			return 0;
 		}
 		break;
Index: sys/dev/pci/drm/i915/i915_driver.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_driver.c,v
retrieving revision 1.22
diff -u -p -r1.22 i915_driver.c
--- sys/dev/pci/drm/i915/i915_driver.c	19 May 2025 21:48:28 -0000	1.22
+++ sys/dev/pci/drm/i915/i915_driver.c	18 Jul 2025 20:20:49 -0000
@@ -1972,7 +1972,7 @@ inteldrm_wsioctl(void *v, u_long cmd, ca
 		case WSDISPLAYIO_PARAM_BRIGHTNESS:
 			bd->props.brightness = dp->curval;
 			backlight_update_status(bd);
-			knote_locked(&dev_priv->drm.note, NOTE_CHANGE);
+			knote(&dev_priv->drm.note, NOTE_CHANGE);
 			return 0;
 		}
 		break;
Index: sys/dev/pci/drm/include/drm/drm_device.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/drm/drm_device.h,v
retrieving revision 1.11
diff -u -p -r1.11 drm_device.h
--- sys/dev/pci/drm/include/drm/drm_device.h	7 Feb 2025 03:03:30 -0000	1.11
+++ sys/dev/pci/drm/include/drm/drm_device.h	18 Jul 2025 20:20:49 -0000
@@ -109,6 +109,7 @@ struct drm_device {
 	bus_dma_tag_t		dmat;
 	bus_space_tag_t		bst;
 
+	struct mutex note_mtx;
 	struct klist note;
 	struct pci_dev  _pdev;
 	struct pci_dev *pdev;
Index: sys/dev/pci/drm/include/drm/drm_file.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/drm/drm_file.h,v
retrieving revision 1.13
diff -u -p -r1.13 drm_file.h
--- sys/dev/pci/drm/include/drm/drm_file.h	18 Jul 2025 00:12:49 -0000	1.13
+++ sys/dev/pci/drm/include/drm/drm_file.h	18 Jul 2025 20:20:49 -0000
@@ -38,7 +38,7 @@
 
 #include <drm/drm_prime.h>
 
-#include <sys/selinfo.h>
+#include <sys/event.h>
 
 struct dma_fence;
 struct drm_file;
@@ -398,7 +398,7 @@ struct drm_file {
 	struct drm_prime_file_private prime;
 
 #ifdef __OpenBSD__
-	struct selinfo rsel;
+	struct klist rklist;
 	SPLAY_ENTRY(drm_file) link;
 #endif
 };