On 20/05/20(Wed) 12:18, Mark Kettenis wrote:
> > Date: Wed, 20 May 2020 11:33:24 +0200
> > From: Martin Pieuchot <[email protected]>
> > 
> > Diff below implements kqfilter for the 3 remaining drivers in the tree,
> > that I could find, supporting poll(2) but not kqueue(2).
> > 
> > magma(4) and spif(4) call seltrue() so their diff is trivial.
> > 
> > This change is required to be able to switch poll(2) and select(2) to
> > use the *kqfilter() handlers on sparc64.  If one values coherency, it
> > also makes sense on its own.
> > 
> > ok?
> 
> Nope.  The filt_vldcwrite() implementation is defenitely wrong as it
> looks at the rx queue instead of the tx queue.

Diff below fixed the cbus_intr_setenabled() line and `avail' calculation.
Is it what you were pointing? 

> But even then, I'm not sure if this is doing the right thing.  Si the
> way the code enables interrupts compatible with kqueue(2)?  In the
> current implementation, enabling interrupts is closely tied to the
> selrecord() call and disabling interrupts happens at the same time as
> the selwakeup().

When a kevent is registered to a kqueue, the corresponding filter
function, pointed by `f_event', is called.  This is similar to calling
`fo_poll' inside pollscan() before going to sleep.

When `f_event' returns a non-0 value, an allocated descriptor representing
the event, `kn' (or knote), is put in the kqueue.

If this didn't happen when the kevent has been registered, either via
kevent(2) or by calling kqueue_register() inside sys_ppoll(), it might
happen when selwakeup() occurs.  Because selwakeup() calls knote(). 

To my understanding this does the same, did I miss anything?

> It really is hard to tell for me to tell what is supposed to happen
> here since there is no kqueue(9) that documents how this is supposed to
> work.

Agreed, that's why it is important to discuss and build knowledge :)

Index: arch/sparc64/dev/vldcp.c
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/dev/vldcp.c,v
retrieving revision 1.19
diff -u -p -r1.19 vldcp.c
--- arch/sparc64/dev/vldcp.c    19 Dec 2019 12:04:38 -0000      1.19
+++ arch/sparc64/dev/vldcp.c    20 May 2020 12:37:27 -0000
@@ -70,6 +70,11 @@ struct vldcp_softc {
 
 int    vldcp_match(struct device *, void *, void *);
 void   vldcp_attach(struct device *, struct device *, void *);
+void   filt_vldcprdetach(struct knote *);
+void   filt_vldcpwdetach(struct knote *);
+int    filt_vldcpread(struct knote *, long);
+int    filt_vldcpwrite(struct knote *, long);
+int    vldcpkqfilter(dev_t, struct knote *);
 
 struct cfattach vldcp_ca = {
        sizeof(struct vldcp_softc), vldcp_match, vldcp_attach
@@ -614,4 +619,122 @@ vldcppoll(dev_t dev, int events, struct 
        }
        splx(s);
        return revents;
+}
+
+void
+filt_vldcprdetach(struct knote *kn)
+{
+       struct vldcp_softc *sc = (void *)kn->kn_hook;
+       int s;
+
+       s = spltty();
+       klist_remove(&sc->sc_rsel.si_note, kn);
+       splx(s);
+}
+
+void
+filt_vldcpwdetach(struct knote *kn)
+{
+       struct vldcp_softc *sc = (void *)kn->kn_hook;
+       int s;
+
+       s = spltty();
+       klist_remove(&sc->sc_wsel.si_note, kn);
+       splx(s);
+}
+
+int
+filt_vldcpread(struct knote *kn, long hint)
+{
+       struct vldcp_softc *sc = (void *)kn->kn_hook;
+       struct ldc_conn *lc = &sc->sc_lc;
+       uint64_t head, tail, avail, state;
+       int s, err;
+
+       s = spltty();
+       err = hv_ldc_rx_get_state(lc->lc_id, &head, &tail, &state);
+       if (err == 0 && state == LDC_CHANNEL_UP && head != tail) {
+               avail = (head - tail) / sizeof(struct ldc_pkt) +
+                   lc->lc_rxq->lq_nentries - 1;
+               avail %= lc->lc_rxq->lq_nentries;
+               kn->kn_data = avail;
+       } else {
+               cbus_intr_setenabled(sc->sc_bustag, sc->sc_rx_ino,
+                   INTR_ENABLED);
+       }
+       splx(s);
+
+       return (kn->kn_data > 0);
+}
+
+int
+filt_vldcwrite(struct knote *kn, long hint)
+{
+       struct vldcp_softc *sc = (void *)kn->kn_hook;
+       struct ldc_conn *lc = &sc->sc_lc;
+       uint64_t head, tail, avail, state;
+       int s, err;
+
+       s = spltty();
+       err = hv_ldc_tx_get_state(lc->lc_id, &head, &tail, &state);
+       if (err == 0 && state == LDC_CHANNEL_UP && head != tail) {
+               avail = (head - tail) / sizeof(struct ldc_pkt) +
+                   lc->lc_txq->lq_nentries - 1;
+               avail %= lc->lc_txq->lq_nentries;
+               kn->kn_data = avail;
+       } else {
+               cbus_intr_setenabled(sc->sc_bustag, sc->sc_tx_ino,
+                   INTR_ENABLED);
+       }
+       splx(s);
+
+       return (kn->kn_data > 0);
+}
+
+const struct filterops vldcpread_filtops = {
+       .f_flags        = FILTEROP_ISFD,
+       .f_attach       = NULL,
+       .f_detach       = filt_vldcprdetach,
+       .f_event        = filt_vldcpread,
+};
+
+const struct filterops vldcpwrite_filtops = {
+       .f_flags        = FILTEROP_ISFD,
+       .f_attach       = NULL,
+       .f_detach       = filt_vldcpwdetach,
+       .f_event        = filt_vldcwrite,
+};
+
+int
+vldcpkqfilter(dev_t dev, struct knote *kn)
+{
+       struct vldcp_softc *sc;
+       struct klist *klist;
+       int s;
+
+       sc = vldcp_lookup(dev);
+       if (sc == NULL)
+               return (ENXIO);
+
+       switch (kn->kn_filter) {
+       case EVFILT_READ:
+               klist = &sc->sc_rsel.si_note;
+               kn->kn_fop = &vldcpread_filtops;
+               break;
+       case EVFILT_WRITE:
+               klist = &sc->sc_wsel.si_note;
+               kn->kn_fop = &vldcpwrite_filtops;
+               break;
+
+       default:
+               return (EINVAL);
+       }
+
+       kn->kn_hook = sc;
+
+       s = spltty();
+       klist_insert(klist, kn);
+       splx(s);
+
+       return (0);
 }
Index: arch/sparc64/include/conf.h
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/include/conf.h,v
retrieving revision 1.25
diff -u -p -r1.25 conf.h
--- arch/sparc64/include/conf.h 13 May 2020 08:10:03 -0000      1.25
+++ arch/sparc64/include/conf.h 20 May 2020 09:15:55 -0000
@@ -64,7 +64,8 @@ cdev_decl(vdsp);
 #define        cdev_gen_init(c,n) { \
        dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
        dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \
-       0, dev_init(c,n,poll), (dev_type_mmap((*))) enodev }
+       0, dev_init(c,n,poll), (dev_type_mmap((*))) enodev, \
+       0, 0, dev_init(c,n,kqfilter) }
 
 cdev_decl(cn);
 
Index: dev/sbus/magma.c
===================================================================
RCS file: /cvs/src/sys/dev/sbus/magma.c,v
retrieving revision 1.31
diff -u -p -r1.31 magma.c
--- dev/sbus/magma.c    18 Feb 2020 00:12:08 -0000      1.31
+++ dev/sbus/magma.c    20 May 2020 09:15:55 -0000
@@ -1340,6 +1340,7 @@ mtty_param(struct tty *tp, struct termio
  *     mbppwrite       write to mbpp
  *     mbppioctl       do ioctl on mbpp
  *     mbpppoll        do poll on mbpp
+ *     mbppkqfilter    kqueue on mbpp
  *     mbpp_rw         general rw routine
  *     mbpp_timeout    rw timeout
  *     mbpp_start      rw start after delay
@@ -1513,6 +1514,12 @@ int
 mbpppoll(dev_t dev, int events, struct proc *p)
 {
        return (seltrue(dev, events, p));
+}
+
+int
+mbppkqfilter(dev_t dev, struct knote *kn)
+{
+       return (seltrue_kqfilter(dev, kn));
 }
 
 int
Index: dev/sbus/spif.c
===================================================================
RCS file: /cvs/src/sys/dev/sbus/spif.c,v
retrieving revision 1.23
diff -u -p -r1.23 spif.c
--- dev/sbus/spif.c     19 Jul 2019 00:17:15 -0000      1.23
+++ dev/sbus/spif.c     20 May 2020 09:15:55 -0000
@@ -91,6 +91,7 @@ int   sbppwrite(dev_t, struct uio *, int);
 int    sbpp_rw(dev_t, struct uio *);
 int    spifppcintr(void *);
 int    sbpppoll(dev_t, int, struct proc *);
+int    sbppkqfilter(dev_t, struct knote *);
 int    sbppioctl(dev_t, u_long, caddr_t, int, struct proc *);
 
 struct cfattach spif_ca = {
@@ -1043,6 +1044,11 @@ int
 sbpppoll(dev_t dev, int events, struct proc *p)
 {
        return (seltrue(dev, events, p));
+}
+int
+sbppkqfilter(dev_t dev, struct knote *kn)
+{
+       return (seltrue_kqfilter(dev, kn));
 }
 
 int

Reply via email to