Diff below extends the existing drmkqfilter() to support EVFILT_READ. This makes drm(4)'s kqueue support in pair with poll().
The event list queried in the filt_drmread() should be protected by the `event_lock' mutex. This could be done by using the `kdev' backpointer as shown in comment. However this would require some plumbing to make use of `minor'. The side effect of this approach would be to reduce the diff with Linux. I'd be interested to hear if somebody sees a different approach. That said, as long as the KERNEL_LOCK() is taken in all these code paths it should be safe to commit the filter as it is. Comments, Oks? Index: sys/conf.h =================================================================== RCS file: /cvs/src/sys/sys/conf.h,v retrieving revision 1.150 diff -u -p -r1.150 conf.h --- sys/conf.h 21 Apr 2020 08:29:27 -0000 1.150 +++ sys/conf.h 27 Apr 2020 14:43:48 -0000 @@ -439,7 +439,7 @@ extern struct cdevsw cdevsw[]; (dev_type_stop((*))) enodev, 0, selfalse, \ (dev_type_mmap((*))) enodev } -/* open, close, read, ioctl, poll, mmap, nokqfilter */ +/* open, close, read, ioctl, poll, mmap, kqfilter */ #define cdev_drm_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), dev_init(c, n, read), \ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ Index: dev/pci/drm/drm_drv.c =================================================================== RCS file: /cvs/src/sys/dev/pci/drm/drm_drv.c,v retrieving revision 1.174 diff -u -p -r1.174 drm_drv.c --- dev/pci/drm/drm_drv.c 7 Apr 2020 13:27:51 -0000 1.174 +++ dev/pci/drm/drm_drv.c 27 Apr 2020 14:43:48 -0000 @@ -484,6 +484,30 @@ filt_drmkms(struct knote *kn, long hint) return (kn->kn_fflags != 0); } +void +filt_drmreaddetach(struct knote *kn) +{ + struct drm_file *file_priv = kn->kn_hook; + int s; + + s = spltty(); + klist_remove(&file_priv->rsel.si_note, kn); + splx(s); +} + +int +filt_drmread(struct knote *kn, long hint) +{ + struct drm_file *file_priv = kn->kn_hook; + int val = 0; + + //mtx_enter(&file_priv->minor->kdev->event_lock); + val = !list_empty(&file_priv->event_list); + //mtx_leave(&file_priv->minor->kdev->event_lock); + + return (val); +} + const struct filterops drm_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, @@ -491,30 +515,51 @@ const struct filterops drm_filtops = { .f_event = filt_drmkms, }; +const struct filterops drmread_filtops = { + .f_flags = FILTEROP_ISFD, + .f_attach = NULL, + .f_detach = filt_drmreaddetach, + .f_event = filt_drmread, +}; + int drmkqfilter(dev_t kdev, struct knote *kn) { struct drm_device *dev = NULL; - int s; + struct drm_file *file_priv = NULL; + int s; dev = drm_get_device_from_kdev(kdev); if (dev == NULL || dev->dev_private == NULL) return (ENXIO); switch (kn->kn_filter) { + case EVFILT_READ: + mutex_lock(&dev->struct_mutex); + file_priv = drm_find_file_by_minor(dev, minor(kdev)); + mutex_unlock(&dev->struct_mutex); + if (file_priv == NULL) + return (ENXIO); + + kn->kn_fop = &drmread_filtops; + kn->kn_hook = file_priv; + + s = spltty(); + klist_insert(&file_priv->rsel.si_note, kn); + splx(s); + break; case EVFILT_DEVICE: kn->kn_fop = &drm_filtops; + kn->kn_hook = dev; + + s = spltty(); + klist_insert(&dev->note, kn); + splx(s); break; default: return (EINVAL); } - kn->kn_hook = dev; - - s = spltty(); - klist_insert(&dev->note, kn); - splx(s); - return (0); } @@ -772,7 +817,6 @@ out: return (gotone); } -/* XXX kqfilter ... */ int drmpoll(dev_t kdev, int events, struct proc *p) {