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 mark D_MPSAFE:



details:   https://anonhg.NetBSD.org/src/rev/2bd2dda496fe
branches:  jmcneill-usbmp
changeset: 771820:2bd2dda496fe
user:      mrg <mrg%NetBSD.org@localhost>
date:      Sat Feb 25 20:52:29 2012 +0000

description:
mark D_MPSAFE:
- spl -> mutex
- convert to SMP usb_detach_wait/wakeup()
- add a IPL_NONE access lock, used in most devsw entry points

diffstat:

 sys/dev/usb/uhid.c |  122 ++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 88 insertions(+), 34 deletions(-)

diffs (truncated from 350 to 300 lines):

diff -r 82286562f93e -r 2bd2dda496fe sys/dev/usb/uhid.c
--- a/sys/dev/usb/uhid.c        Sat Feb 25 20:49:17 2012 +0000
+++ b/sys/dev/usb/uhid.c        Sat Feb 25 20:52:29 2012 +0000
@@ -1,12 +1,12 @@
-/*     $NetBSD: uhid.c,v 1.84.12.1 2012/02/24 09:11:43 mrg Exp $       */
+/*     $NetBSD: uhid.c,v 1.84.12.2 2012/02/25 20:52:29 mrg Exp $       */
 
 /*
- * Copyright (c) 1998, 2004, 2008 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 2004, 2008, 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
  * by Lennart Augustsson (lennart%augustsson.net@localhost) at
- * Carlstedt Research & Technology.
+ * Carlstedt Research & Technology and Matthew R. Green (mrg%eterna.com.au@localhost).
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.84.12.1 2012/02/24 09:11:43 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.84.12.2 2012/02/25 20:52:29 mrg Exp $");
 
 #include "opt_compat_netbsd.h"
 
@@ -78,6 +78,11 @@
 struct uhid_softc {
        struct uhidev sc_hdev;
 
+       kmutex_t sc_access_lock; /* serialises syscall accesses */
+       kmutex_t sc_lock;       /* protects refcnt, others */
+       kcondvar_t sc_cv;
+       kcondvar_t sc_detach_cv;
+
        int sc_isize;
        int sc_osize;
        int sc_fsize;
@@ -110,7 +115,7 @@
 
 const struct cdevsw uhid_cdevsw = {
        uhidopen, uhidclose, uhidread, uhidwrite, uhidioctl,
-       nostop, notty, uhidpoll, nommap, uhidkqfilter, D_OTHER,
+       nostop, notty, uhidpoll, nommap, uhidkqfilter, D_OTHER | D_MPSAFE,
 };
 
 Static void uhid_intr(struct uhidev *, void *, u_int len);
@@ -168,6 +173,11 @@
        aprint_normal(": input=%d, output=%d, feature=%d\n",
               sc->sc_isize, sc->sc_osize, sc->sc_fsize);
 
+       mutex_init(&sc->sc_access_lock, MUTEX_DEFAULT, IPL_NONE);
+       mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_USB);
+       cv_init(&sc->sc_cv, "uhidrea");
+       cv_init(&sc->sc_detach_cv, "uhiddet");
+
        if (!pmf_device_register(self, NULL, NULL))
                aprint_error_dev(self, "couldn't establish power handler\n");
 
@@ -192,23 +202,23 @@
 uhid_detach(device_t self, int flags)
 {
        struct uhid_softc *sc = device_private(self);
-       int s;
        int maj, mn;
 
        DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags));
 
        sc->sc_dying = 1;
 
+       mutex_enter(&sc->sc_lock);
        if (sc->sc_hdev.sc_state & UHIDEV_OPEN) {
-               s = splusb();
                if (--sc->sc_refcnt >= 0) {
                        /* Wake everyone */
-                       wakeup(&sc->sc_q);
+                       cv_broadcast(&sc->sc_cv);
                        /* Wait for processes to go away. */
-                       usb_detach_wait(sc->sc_hdev.sc_dev);
+                       usb_detach_waitcv(sc->sc_hdev.sc_dev,
+                           &sc->sc_detach_cv, &sc->sc_lock);
                }
-               splx(s);
        }
+       mutex_exit(&sc->sc_lock);
 
        /* locate the major number */
        maj = cdevsw_lookup_major(&uhid_cdevsw);
@@ -222,6 +232,10 @@
                           sc->sc_hdev.sc_parent->sc_udev,
                           sc->sc_hdev.sc_dev);
 #endif
+       cv_destroy(&sc->sc_cv);
+       cv_destroy(&sc->sc_detach_cv);
+       mutex_destroy(&sc->sc_lock);
+       mutex_destroy(&sc->sc_access_lock);
        seldestroy(&sc->sc_rsel);
        softint_disestablish(sc->sc_sih);
 
@@ -244,18 +258,20 @@
        }
 #endif
 
+       mutex_enter(&sc->sc_lock);
        (void)b_to_q(data, len, &sc->sc_q);
 
        if (sc->sc_state & UHID_ASLP) {
                sc->sc_state &= ~UHID_ASLP;
                DPRINTFN(5, ("uhid_intr: waking %p\n", &sc->sc_q));
-               wakeup(&sc->sc_q);
+               cv_broadcast(&sc->sc_cv);
        }
        selnotify(&sc->sc_rsel, 0, 0);
        if (sc->sc_async != NULL) {
                DPRINTFN(3, ("uhid_intr: sending SIGIO %p\n", sc->sc_async));
                softint_schedule(sc->sc_sih);
        }
+       mutex_exit(&sc->sc_lock);
 }
 
 void
@@ -272,8 +288,7 @@
 }
 
 int
-uhidopen(dev_t dev, int flag, int mode,
-    struct lwp *l)
+uhidopen(dev_t dev, int flag, int mode, struct lwp *l)
 {
        struct uhid_softc *sc;
        int error;
@@ -287,16 +302,23 @@
        if (sc->sc_dying)
                return (ENXIO);
 
+       mutex_enter(&sc->sc_access_lock);
        error = uhidev_open(&sc->sc_hdev);
-       if (error)
+       if (error) {
+               mutex_exit(&sc->sc_access_lock);
                return (error);
+       }
+       mutex_exit(&sc->sc_access_lock);
 
        if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1) {
+               mutex_enter(&sc->sc_access_lock);
                uhidev_close(&sc->sc_hdev);
+               mutex_exit(&sc->sc_access_lock);
                return (ENOMEM);
        }
        sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK);
        sc->sc_state &= ~UHID_IMMED;
+
        mutex_enter(proc_lock);
        sc->sc_async = NULL;
        mutex_exit(proc_lock);
@@ -305,8 +327,7 @@
 }
 
 int
-uhidclose(dev_t dev, int flag, int mode,
-    struct lwp *l)
+uhidclose(dev_t dev, int flag, int mode, struct lwp *l)
 {
        struct uhid_softc *sc;
 
@@ -316,10 +337,14 @@
 
        clfree(&sc->sc_q);
        free(sc->sc_obuf, M_USBDEV);
+
        mutex_enter(proc_lock);
        sc->sc_async = NULL;
        mutex_exit(proc_lock);
+
+       mutex_enter(&sc->sc_access_lock);
        uhidev_close(&sc->sc_hdev);
+       mutex_exit(&sc->sc_access_lock);
 
        return (0);
 }
@@ -327,7 +352,6 @@
 int
 uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag)
 {
-       int s;
        int error = 0;
        int extra;
        size_t length;
@@ -345,15 +369,15 @@
                return (uiomove(buffer+extra, sc->sc_isize, uio));
        }
 
-       s = splusb();
+       mutex_enter(&sc->sc_lock);
        while (sc->sc_q.c_cc == 0) {
                if (flag & IO_NDELAY) {
-                       splx(s);
+                       mutex_exit(&sc->sc_lock);
                        return (EWOULDBLOCK);
                }
                sc->sc_state |= UHID_ASLP;
                DPRINTFN(5, ("uhidread: sleep on %p\n", &sc->sc_q));
-               error = tsleep(&sc->sc_q, PZERO | PCATCH, "uhidrea", 0);
+               error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock);
                DPRINTFN(5, ("uhidread: woke, error=%d\n", error));
                if (sc->sc_dying)
                        error = EIO;
@@ -362,7 +386,7 @@
                        break;
                }
        }
-       splx(s);
+       mutex_exit(&sc->sc_lock);
 
        /* Transfer as many chunks as possible. */
        while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) {
@@ -390,10 +414,19 @@
 
        sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev));
 
+       mutex_enter(&sc->sc_lock);
        sc->sc_refcnt++;
+       mutex_exit(&sc->sc_lock);
+
+       mutex_enter(&sc->sc_access_lock);
        error = uhid_do_read(sc, uio, flag);
+       mutex_exit(&sc->sc_access_lock);
+
+       mutex_enter(&sc->sc_lock);
        if (--sc->sc_refcnt < 0)
-               usb_detach_wakeup(sc->sc_hdev.sc_dev);
+               usb_detach_broadcast(sc->sc_hdev.sc_dev, &sc->sc_detach_cv);
+       mutex_exit(&sc->sc_lock);
+
        return (error);
 }
 
@@ -432,10 +465,18 @@
 
        sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev));
 
+       mutex_enter(&sc->sc_lock);
        sc->sc_refcnt++;
+       mutex_exit(&sc->sc_lock);
+
+       mutex_enter(&sc->sc_access_lock);
        error = uhid_do_write(sc, uio, flag);
+       mutex_exit(&sc->sc_access_lock);
+
+       mutex_enter(&sc->sc_lock);
        if (--sc->sc_refcnt < 0)
-               usb_detach_wakeup(sc->sc_hdev.sc_dev);
+               usb_detach_broadcast(sc->sc_hdev.sc_dev, &sc->sc_detach_cv);
+       mutex_exit(&sc->sc_lock);
        return (error);
 }
 
@@ -605,11 +646,25 @@
        int error;
 
        sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev));
+       if (sc == NULL)
+               return ENXIO;
 
+       if (sc->sc_dying)
+               return EIO;
+
+       mutex_enter(&sc->sc_lock);
        sc->sc_refcnt++;
+       mutex_exit(&sc->sc_lock);
+
+       mutex_enter(&sc->sc_access_lock);
        error = uhid_do_ioctl(sc, cmd, addr, flag, l);
+       mutex_exit(&sc->sc_access_lock);
+
+       mutex_enter(&sc->sc_lock);
        if (--sc->sc_refcnt < 0)
-               usb_detach_wakeup(sc->sc_hdev.sc_dev);
+               usb_detach_broadcast(sc->sc_hdev.sc_dev, &sc->sc_detach_cv);
+       mutex_exit(&sc->sc_lock);
+
        return (error);
 }
 
@@ -618,14 +673,15 @@
 {
        struct uhid_softc *sc;
        int revents = 0;
-       int s;
 
        sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev));
+       if (sc == NULL)
+               return ENXIO;
 
        if (sc->sc_dying)
-               return (POLLHUP);
+               return EIO;



Home | Main Index | Thread Index | Old Index