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