Source-Changes-HG archive

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

[src/jmcneill-usbmp]: src/sys/dev/usb port this to usbmp and also make it lar...



details:   https://anonhg.NetBSD.org/src/rev/1a9ce0ff5b87
branches:  jmcneill-usbmp
changeset: 771849:1a9ce0ff5b87
user:      mrg <mrg%NetBSD.org@localhost>
date:      Sat May 12 21:28:58 2012 +0000

description:
port this to usbmp and also make it largely MPSAFE, but not yet enough
for D_MPSAFE to be added.  should be merge-ready now, but needs testing.

diffstat:

 sys/dev/usb/ugen.c |  142 +++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 95 insertions(+), 47 deletions(-)

diffs (truncated from 472 to 300 lines):

diff -r 7936100fcc49 -r 1a9ce0ff5b87 sys/dev/usb/ugen.c
--- a/sys/dev/usb/ugen.c        Mon Apr 30 02:42:32 2012 +0000
+++ b/sys/dev/usb/ugen.c        Sat May 12 21:28:58 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ugen.c,v 1.114.2.4 2012/04/29 23:05:01 mrg Exp $       */
+/*     $NetBSD: ugen.c,v 1.114.2.5 2012/05/12 21:28:58 mrg Exp $       */
 
 /*
  * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ugen.c,v 1.114.2.4 2012/04/29 23:05:01 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ugen.c,v 1.114.2.5 2012/05/12 21:28:58 mrg Exp $");
 
 #include "opt_compat_netbsd.h"
 
@@ -108,12 +108,17 @@
                void *dmabuf;
                u_int16_t sizes[UGEN_NISORFRMS];
        } isoreqs[UGEN_NISOREQS];
+       /* Keep this last; we don't overwrite it in ugen_set_config() */
+       kcondvar_t              cv;
 };
 
 struct ugen_softc {
        device_t sc_dev;                /* base device */
        usbd_device_handle sc_udev;
 
+       kmutex_t                sc_lock;
+       kcondvar_t              sc_detach_cv;
+
        char sc_is_open[USB_MAX_ENDPOINTS];
        struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2];
 #define OUT 0
@@ -201,6 +206,9 @@
        aprint_naive("\n");
        aprint_normal("\n");
 
+       mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_USB);
+       cv_init(&sc->sc_detach_cv, "ugendet");
+
        devinfop = usbd_devinfo_alloc(uaa->device, 0);
        aprint_normal_dev(self, "%s\n", devinfop);
        usbd_devinfo_free(devinfop);
@@ -233,6 +241,7 @@
 
                        sce = &sc->sc_endpoints[i][dir];
                        selinit(&sce->rsel);
+                       cv_init(&sce->cv, "ugensce");
                }
        }
 
@@ -256,7 +265,7 @@
        u_int8_t niface, nendpt;
        int ifaceno, endptno, endpt;
        usbd_status err;
-       int dir;
+       int dir, i;
 
        DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
                    device_xname(sc->sc_dev), configno, sc));
@@ -284,7 +293,15 @@
        err = usbd_interface_count(dev, &niface);
        if (err)
                return (err);
-       memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
+
+       /* Clear out the old info, but leave the cv initialised. */
+       for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
+               for (dir = OUT; dir <= IN; dir++) {
+                       sce = &sc->sc_endpoints[i][dir];
+                       memset(sce, 0, offsetof(struct ugen_endpoint, cv));
+               }
+       }
+
        for (ifaceno = 0; ifaceno < niface; ifaceno++) {
                DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
                err = usbd_device2interface_handle(dev, ifaceno, &iface);
@@ -537,7 +554,6 @@
        u_int32_t n, tn;
        usbd_xfer_handle xfer;
        usbd_status err;
-       int s;
        int error = 0;
 
        DPRINTFN(5, ("%s: ugenread: %d\n", device_xname(sc->sc_dev), endpt));
@@ -562,15 +578,17 @@
        switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
        case UE_INTERRUPT:
                /* Block until activity occurred. */
-               s = splusb();
+               mutex_enter(&sc->sc_lock);
                while (sce->q.c_cc == 0) {
                        if (flag & IO_NDELAY) {
-                               splx(s);
+                               mutex_exit(&sc->sc_lock);
                                return (EWOULDBLOCK);
                        }
                        sce->state |= UGEN_ASLP;
                        DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
-                       error = tsleep(sce, PZERO | PCATCH, "ugenri", mstohz(sce->timeout));
+                       /* "ugenri" */
+                       error = cv_timedwait_sig(&sce->cv, &sc->sc_lock,
+                           mstohz(sce->timeout));
                        DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
                        if (sc->sc_dying)
                                error = EIO;
@@ -579,7 +597,7 @@
                                break;
                        }
                }
-               splx(s);
+               mutex_exit(&sc->sc_lock);
 
                /* Transfer as many chunks as possible. */
                while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) {
@@ -603,9 +621,9 @@
                                     uio->uio_resid, sce->ra_wb_used));
                        xfer = sce->ra_wb_xfer;
 
-                       s = splusb();
+                       mutex_enter(&sc->sc_lock);
                        if (sce->ra_wb_used == 0 && flag & IO_NDELAY) {
-                               splx(s);
+                               mutex_exit(&sc->sc_lock);
                                return (EWOULDBLOCK);
                        }
                        while (uio->uio_resid > 0 && !error) {
@@ -614,8 +632,9 @@
                                        DPRINTFN(5,
                                                 ("ugenread: sleep on %p\n",
                                                  sce));
-                                       error = tsleep(sce, PZERO | PCATCH,
-                                                      "ugenrb", mstohz(sce->timeout));
+                                       /* "ugenrb" */
+                                       error = cv_timedwait_sig(&sce->cv,
+                                           &sc->sc_lock, mstohz(sce->timeout));
                                        DPRINTFN(5,
                                                 ("ugenread: woke, error=%d\n",
                                                  error));
@@ -667,7 +686,7 @@
                                                sce->state |= UGEN_RA_WB_STOP;
                                }
                        }
-                       splx(s);
+                       mutex_exit(&sc->sc_lock);
                        break;
                }
                xfer = usbd_alloc_xfer(sc->sc_udev);
@@ -698,15 +717,17 @@
                usbd_free_xfer(xfer);
                break;
        case UE_ISOCHRONOUS:
-               s = splusb();
+               mutex_enter(&sc->sc_lock);
                while (sce->cur == sce->fill) {
                        if (flag & IO_NDELAY) {
-                               splx(s);
+                               mutex_exit(&sc->sc_lock);
                                return (EWOULDBLOCK);
                        }
                        sce->state |= UGEN_ASLP;
+                       /* "ugenri" */
                        DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
-                       error = tsleep(sce, PZERO | PCATCH, "ugenri", mstohz(sce->timeout));
+                       error = cv_timedwait_sig(&sce->cv, &sc->sc_lock,
+                           mstohz(sce->timeout));
                        DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
                        if (sc->sc_dying)
                                error = EIO;
@@ -729,10 +750,10 @@
                        if (error)
                                break;
                        sce->cur += n;
-                       if(sce->cur >= sce->limit)
+                       if (sce->cur >= sce->limit)
                                sce->cur = sce->ibuf;
                }
-               splx(s);
+               mutex_exit(&sc->sc_lock);
                break;
 
 
@@ -753,10 +774,17 @@
        if (sc == NULL)
                return ENXIO;
 
+       mutex_enter(&sc->sc_lock);
        sc->sc_refcnt++;
+       mutex_exit(&sc->sc_lock);
+
        error = ugen_do_read(sc, endpt, uio, flag);
+
+       mutex_enter(&sc->sc_lock);
        if (--sc->sc_refcnt < 0)
-               usb_detach_wakeupold(sc->sc_dev);
+               usb_detach_broadcast(sc->sc_dev, &sc->sc_detach_cv);
+       mutex_exit(&sc->sc_lock);
+
        return (error);
 }
 
@@ -767,7 +795,6 @@
        struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT];
        u_int32_t n;
        int error = 0;
-       int s;
        u_int32_t tn;
        char *dbuf;
        usbd_xfer_handle xfer;
@@ -799,10 +826,10 @@
                                     uio->uio_resid, sce->ra_wb_used));
                        xfer = sce->ra_wb_xfer;
 
-                       s = splusb();
+                       mutex_enter(&sc->sc_lock);
                        if (sce->ra_wb_used == sce->limit - sce->ibuf &&
                            flag & IO_NDELAY) {
-                               splx(s);
+                               mutex_exit(&sc->sc_lock);
                                return (EWOULDBLOCK);
                        }
                        while (uio->uio_resid > 0 && !error) {
@@ -812,8 +839,9 @@
                                        DPRINTFN(5,
                                                 ("ugenwrite: sleep on %p\n",
                                                  sce));
-                                       error = tsleep(sce, PZERO | PCATCH,
-                                                      "ugenwb", mstohz(sce->timeout));
+                                       /* "ugenwb" */
+                                       error = cv_timedwait_sig(&sce->cv,
+                                           &sc->sc_lock, mstohz(sce->timeout));
                                        DPRINTFN(5,
                                                 ("ugenwrite: woke, error=%d\n",
                                                  error));
@@ -872,7 +900,7 @@
                                                sce->state |= UGEN_RA_WB_STOP;
                                }
                        }
-                       splx(s);
+                       mutex_exit(&sc->sc_lock);
                        break;
                }
                xfer = usbd_alloc_xfer(sc->sc_udev);
@@ -938,10 +966,17 @@
        if (sc == NULL)
                return ENXIO;
 
+       mutex_enter(&sc->sc_lock);
        sc->sc_refcnt++;
+       mutex_exit(&sc->sc_lock);
+
        error = ugen_do_write(sc, endpt, uio, flag);
+
+       mutex_enter(&sc->sc_lock);
        if (--sc->sc_refcnt < 0)
-               usb_detach_wakeupold(sc->sc_dev);
+               usb_detach_broadcast(sc->sc_dev, &sc->sc_detach_cv);
+       mutex_exit(&sc->sc_lock);
+
        return (error);
 }
 
@@ -965,7 +1000,6 @@
        struct ugen_softc *sc = device_private(self);
        struct ugen_endpoint *sce;
        int i, dir;
-       int s;
        int maj, mn;
 
        DPRINTF(("ugen_detach: sc=%p flags=%d\n", sc, flags));
@@ -981,15 +1015,15 @@
                }
        }
 
-       s = splusb();
+       mutex_enter(&sc->sc_lock);
        if (--sc->sc_refcnt >= 0) {
                /* Wake everyone */
                for (i = 0; i < USB_MAX_ENDPOINTS; i++)
-                       wakeup(&sc->sc_endpoints[i][IN]);
+                       cv_signal(&sc->sc_endpoints[i][IN].cv);
                /* Wait for processes to go away. */
-               usb_detach_waitold(sc->sc_dev);
+               usb_detach_wait(sc->sc_dev, &sc->sc_detach_cv, &sc->sc_lock);
        }
-       splx(s);
+       mutex_exit(&sc->sc_lock);
 
        /* locate the major number */
        maj = cdevsw_lookup_major(&ugen_cdevsw);
@@ -1005,9 +1039,13 @@
                for (dir = OUT; dir <= IN; dir++) {
                        sce = &sc->sc_endpoints[i][dir];
                        seldestroy(&sce->rsel);
+                       cv_destroy(&sce->cv);
                }
        }



Home | Main Index | Thread Index | Old Index