Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/nick-nhusb]: src/sys/dev/usb Make ucom(4) MP safe
details: https://anonhg.NetBSD.org/src/rev/44fbd24d507a
branches: nick-nhusb
changeset: 334242:44fbd24d507a
user: skrll <skrll%NetBSD.org@localhost>
date: Sat Sep 19 07:39:51 2015 +0000
description:
Make ucom(4) MP safe
diffstat:
sys/dev/usb/ucom.c | 247 +++++++++++++++++++++++++++++++++++-----------------
1 files changed, 167 insertions(+), 80 deletions(-)
diffs (truncated from 685 to 300 lines):
diff -r 1084f7160a60 -r 44fbd24d507a sys/dev/usb/ucom.c
--- a/sys/dev/usb/ucom.c Sun Sep 13 09:27:54 2015 +0000
+++ b/sys/dev/usb/ucom.c Sat Sep 19 07:39:51 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ucom.c,v 1.108.2.7 2015/07/23 07:36:33 skrll Exp $ */
+/* $NetBSD: ucom.c,v 1.108.2.8 2015/09/19 07:39:51 skrll Exp $ */
/*
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.108.2.7 2015/07/23 07:36:33 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.108.2.8 2015/09/19 07:39:51 skrll Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -179,7 +179,11 @@
struct pps_state sc_pps_state; /* pps state */
- krndsource_t sc_rndsource; /* random source */
+ krndsource_t sc_rndsource; /* random source */
+
+ kmutex_t *sc_lock;
+ kcondvar_t sc_opencv;
+ kcondvar_t sc_detachcv;
};
dev_type_open(ucomopen);
@@ -203,7 +207,7 @@
.d_mmap = nommap,
.d_kqfilter = ttykqfilter,
.d_discard = nodiscard,
- .d_flag = D_TTY
+ .d_flag = D_TTY | D_MPSAFE
};
static void ucom_cleanup(struct ucom_softc *);
@@ -278,7 +282,10 @@
sc->sc_refcnt = 0;
sc->sc_dying = 0;
- sc->sc_si = softint_establish(SOFTINT_NET, ucom_softintr, sc);
+ sc->sc_si = softint_establish(SOFTINT_USB, ucom_softintr, sc);
+ sc->sc_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_SOFTUSB);
+ cv_init(&sc->sc_opencv, "ucomopen");
+ cv_init(&sc->sc_detachcv, "ucomdtch");
tp = tty_alloc();
tp->t_oproc = ucomstart;
@@ -303,14 +310,17 @@
struct ucom_softc *sc = device_private(self);
struct tty *tp = sc->sc_tty;
int maj, mn;
- int s, i;
+ int i;
UCOMHIST_FUNC(); UCOMHIST_CALLED();
DPRINTF("sc=%p flags=%d tp=%p", sc, flags, tp, 0);
DPRINTF("... pipe=%d,%d",sc->sc_bulkin_no, sc->sc_bulkout_no, 0, 0);
+ mutex_enter(sc->sc_lock);
sc->sc_dying = 1;
+ mutex_exit(sc->sc_lock);
+
pmf_device_deregister(self);
if (sc->sc_bulkin_pipe != NULL)
@@ -318,8 +328,8 @@
if (sc->sc_bulkout_pipe != NULL)
usbd_abort_pipe(sc->sc_bulkout_pipe);
- s = splusb();
- if (--sc->sc_refcnt >= 0) {
+ mutex_enter(sc->sc_lock);
+ while (sc->sc_refcnt > 0) {
/* Wake up anyone waiting */
if (tp != NULL) {
mutex_spin_enter(&tty_lock);
@@ -329,11 +339,11 @@
mutex_spin_exit(&tty_lock);
}
/* Wait for processes to go away. */
- usb_detach_waitold(sc->sc_dev);
+ usb_detach_wait(sc->sc_dev, &sc->sc_detachcv, sc->sc_lock);
}
softint_disestablish(sc->sc_si);
- splx(s);
+ mutex_exit(sc->sc_lock);
/* locate the major number */
maj = cdevsw_lookup_major(&ucom_cdevsw);
@@ -365,6 +375,10 @@
/* Detach the random source */
rnd_detach_source(&sc->sc_rndsource);
+ mutex_destroy(sc->sc_lock);
+ cv_destroy(&sc->sc_opencv);
+ cv_destroy(&sc->sc_detachcv);
+
return 0;
}
@@ -379,7 +393,9 @@
switch (act) {
case DVACT_DEACTIVATE:
+ mutex_enter(sc->sc_lock);
sc->sc_dying = 1;
+ mutex_exit(sc->sc_lock);
return 0;
default:
return EOPNOTSUPP;
@@ -393,13 +409,15 @@
UCOMHIST_FUNC(); UCOMHIST_CALLED();
+ KASSERT(mutex_owned(sc->sc_lock));
/*
* Hang up if necessary. Wait a bit, so the other side has time to
* notice even if we immediately open the port again.
*/
if (ISSET(tp->t_cflag, HUPCL)) {
ucom_dtr(sc, 0);
- (void)tsleep(sc, TTIPRI, ttclos, hz);
+ /* XXX will only timeout */
+ (void) kpause(ttclos, false, hz, sc->sc_lock);
}
}
@@ -411,7 +429,7 @@
struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit);
struct ucom_buffer *ub;
struct tty *tp;
- int s, i;
+ int i;
int error;
UCOMHIST_FUNC(); UCOMHIST_CALLED();
@@ -419,31 +437,38 @@
if (sc == NULL)
return ENXIO;
- if (sc->sc_dying)
+ mutex_enter(sc->sc_lock);
+ if (sc->sc_dying) {
+ mutex_exit(sc->sc_lock);
return EIO;
+ }
- if (!device_is_active(sc->sc_dev))
+ if (!device_is_active(sc->sc_dev)) {
+ mutex_exit(sc->sc_lock);
return ENXIO;
+ }
tp = sc->sc_tty;
DPRINTF("unit=%d, tp=%p\n", unit, tp, 0, 0);
- if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
+ if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) {
+ mutex_exit(sc->sc_lock);
return EBUSY;
-
- s = spltty();
+ }
/*
* Do the following iff this is a first open.
*/
- while (sc->sc_opening)
- tsleep(&sc->sc_opening, PRIBIO, "ucomop", 0);
+ while (sc->sc_opening) {
+ error = cv_wait_sig(&sc->sc_opencv, sc->sc_lock);
- if (sc->sc_dying) {
- splx(s);
- return EIO;
+ if (error) {
+ mutex_exit(sc->sc_lock);
+ return error;
+ }
}
+
sc->sc_opening = 1;
if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
@@ -457,8 +482,8 @@
if (error) {
ucom_cleanup(sc);
sc->sc_opening = 0;
- wakeup(&sc->sc_opening);
- splx(s);
+ cv_signal(&sc->sc_opencv);
+ mutex_exit(sc->sc_lock);
return error;
}
}
@@ -577,8 +602,8 @@
}
sc->sc_opening = 0;
- wakeup(&sc->sc_opening);
- splx(s);
+ cv_signal(&sc->sc_opencv);
+ mutex_exit(sc->sc_lock);
error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
if (error)
@@ -614,13 +639,15 @@
usbd_close_pipe(sc->sc_bulkin_pipe);
sc->sc_bulkin_pipe = NULL;
fail_0:
+ mutex_enter(sc->sc_lock);
sc->sc_opening = 0;
- wakeup(&sc->sc_opening);
- splx(s);
+ cv_signal(&sc->sc_opencv);
+ mutex_exit(sc->sc_lock);
+
return error;
bad:
- s = spltty();
+ mutex_spin_enter(&tty_lock);
CLR(tp->t_state, TS_BUSY);
if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
/*
@@ -629,7 +656,7 @@
*/
ucom_cleanup(sc);
}
- splx(s);
+ mutex_spin_exit(&tty_lock);
return error;
}
@@ -639,7 +666,6 @@
{
struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
struct tty *tp;
- int s;
UCOMHIST_FUNC(); UCOMHIST_CALLED();
@@ -648,12 +674,13 @@
if (sc == NULL)
return 0;
+ mutex_enter(sc->sc_lock);
tp = sc->sc_tty;
- if (!ISSET(tp->t_state, TS_ISOPEN))
- return 0;
+ if (!ISSET(tp->t_state, TS_ISOPEN)) {
+ goto out;
+ }
- s = spltty();
sc->sc_refcnt++;
(*tp->t_linesw->l_close)(tp, flag);
@@ -672,8 +699,10 @@
sc->sc_methods->ucom_close(sc->sc_parent, sc->sc_portno);
if (--sc->sc_refcnt < 0)
- usb_detach_wakeupold(sc->sc_dev);
- splx(s);
+ usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv);
+
+out:
+ mutex_exit(sc->sc_lock);
return 0;
}
@@ -687,15 +716,26 @@
UCOMHIST_FUNC(); UCOMHIST_CALLED();
- if (sc == NULL || sc->sc_dying)
+ if (sc == NULL)
return EIO;
+ mutex_enter(sc->sc_lock);
+ if (sc->sc_dying) {
+ mutex_exit(sc->sc_lock);
+ return EIO;
+ }
+
tp = sc->sc_tty;
sc->sc_refcnt++;
+ mutex_exit(sc->sc_lock);
error = ((*tp->t_linesw->l_read)(tp, uio, flag));
+ mutex_enter(sc->sc_lock);
Home |
Main Index |
Thread Index |
Old Index