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