#include <sys/vnode.h>
#include <sys/event.h>
#include <sys/sysctl.h>
+#include <sys/devfs.h>
#include <sys/thread2.h>
#include <bus/usb/usb.h>
struct ums_softc {
device_t sc_dev; /* base device */
+ cdev_t sc_cdev;
usbd_interface_handle sc_iface; /* interface */
usbd_pipe_handle sc_intrpipe; /* interrupt pipe */
int sc_ep_addr;
sc->status.button = sc->status.obutton = 0;
sc->status.dx = sc->status.dy = sc->status.dz = 0;
- make_dev(&ums_ops, device_get_unit(self),
- UID_ROOT, GID_OPERATOR,
- 0644, "ums%d", device_get_unit(self));
+ sc->sc_cdev = make_dev(&ums_ops, device_get_unit(self),
+ UID_ROOT, GID_OPERATOR,
+ 0644, "ums%d", device_get_unit(self));
+ reference_dev(sc->sc_cdev);
if (usbd_get_quirks(uaa->device)->uq_flags & UQ_SPUR_BUT_UP) {
DPRINTF(("%s: Spurious button up events\n",
sc->state &= ~UMS_ASLEEP;
wakeup(sc);
}
- KNOTE(&sc->rkq.ki_note, 0);
dev_ops_remove_minor(&ums_ops, /*-1, */device_get_unit(self));
+ devfs_assume_knotes(sc->sc_cdev, &sc->rkq);
+ release_dev(sc->sc_cdev);
+ sc->sc_cdev = NULL;
return 0;
}
#ifndef _SYS_SYSREF_H_
#include <sys/sysref.h>
#endif
+#ifndef _SYS_EVENT_H_
+#include <sys/event.h>
+#endif
#include <libprop/proplib.h>
#define SPECNAMELEN 63
time_t si_lastwrite; /* time_second */
struct vm_object *si_object; /* vm_pager support */
prop_dictionary_t si_dict;
+ struct kqinfo si_kqinfo; /* degenerate delegated knotes */
};
#define SI_UNUSED01 0x0001
struct devfs_node *devfs_find_device_node_by_name(struct devfs_node *, char *);
cdev_t devfs_new_cdev(struct dev_ops *, int, struct dev_ops *);
+void devfs_assume_knotes(cdev_t dev, struct kqinfo *kqi);
cdev_t devfs_find_device_by_name(const char *, ...) __printflike(1, 2);
cdev_t devfs_find_device_by_udev(udev_t);
{
}
+static int
+devfs_detached_filter_eof(struct knote *kn, long hint)
+{
+ kn->kn_flags |= EV_EOF;
+ return (1);
+}
+
+static void
+devfs_detached_filter_detach(struct knote *kn)
+{
+ cdev_t dev = (cdev_t)kn->kn_hook;
+
+ knote_remove(&dev->si_kqinfo.ki_note, kn);
+}
+
+static struct filterops devfs_detached_filterops =
+ { FILTEROP_ISFD, NULL,
+ devfs_detached_filter_detach,
+ devfs_detached_filter_eof };
+
+/*
+ * Delegates knote filter handling responsibility to devfs
+ *
+ * Any device that implements kqfilter event handling and could be detached
+ * or shut down out from under the kevent subsystem must allow devfs to
+ * assume responsibility for any knotes it may hold.
+ */
+void
+devfs_assume_knotes(cdev_t dev, struct kqinfo *kqi)
+{
+ struct knote *kn;
+
+ lwkt_gettoken(&kq_token);
+
+ while (!SLIST_EMPTY(&kqi->ki_note)) {
+ kn = SLIST_FIRST(&kqi->ki_note);
+ knote_remove(&kqi->ki_note, kn);
+ kn->kn_fop = &devfs_detached_filterops;
+ kn->kn_hook = (caddr_t)dev;
+ knote_insert(&dev->si_kqinfo.ki_note, kn);
+ }
+
+ /*
+ * These should probably be activated individually, but doing so
+ * would require refactoring kq's public in-kernel interface.
+ */
+ KNOTE(&dev->si_kqinfo.ki_note, 0);
+
+ lwkt_reltoken(&kq_token);
+}
+
/*
* Links a given cdev into the dev list.
*/