Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/usb Optimize for higher speeds, e.g. when used as pa...
details: https://anonhg.NetBSD.org/src/rev/6fdecf8e2209
branches: trunk
changeset: 750563:6fdecf8e2209
user: martin <martin%NetBSD.org@localhost>
date: Wed Jan 06 20:37:56 2010 +0000
description:
Optimize for higher speeds, e.g. when used as part of a 3G modem.
Contributed anonymously.
diffstat:
sys/dev/usb/ucom.c | 561 +++++++++++++++++++++++++++++++++++-----------------
1 files changed, 376 insertions(+), 185 deletions(-)
diffs (truncated from 877 to 300 lines):
diff -r 2da6612c0de5 -r 6fdecf8e2209 sys/dev/usb/ucom.c
--- a/sys/dev/usb/ucom.c Wed Jan 06 20:16:57 2010 +0000
+++ b/sys/dev/usb/ucom.c Wed Jan 06 20:37:56 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ucom.c,v 1.81 2009/12/06 21:40:31 dyoung Exp $ */
+/* $NetBSD: ucom.c,v 1.82 2010/01/06 20:37:56 martin 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.81 2009/12/06 21:40:31 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.82 2010/01/06 20:37:56 martin Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -48,6 +48,7 @@
#include <sys/vnode.h>
#include <sys/device.h>
#include <sys/poll.h>
+#include <sys/queue.h>
#include <sys/kauth.h>
#if defined(__NetBSD__)
#include "rnd.h"
@@ -87,6 +88,22 @@
#define UCOMDIALOUT(x) (minor(x) & UCOMDIALOUT_MASK)
#define UCOMCALLUNIT(x) (minor(x) & UCOMCALLUNIT_MASK)
+/*
+ * XXX: We can submit multiple input/output buffers to the usb stack
+ * to improve throughput, but the usb stack is too lame to deal with this
+ * in a number of places.
+ */
+#define UCOM_IN_BUFFS 1
+#define UCOM_OUT_BUFFS 1
+
+struct ucom_buffer {
+ SIMPLEQ_ENTRY(ucom_buffer) ub_link;
+ usbd_xfer_handle ub_xfer;
+ u_char *ub_data;
+ u_int ub_len;
+ u_int ub_index;
+};
+
struct ucom_softc {
USBBASEDEVICE sc_dev; /* base device */
@@ -96,18 +113,21 @@
int sc_bulkin_no; /* bulk in endpoint address */
usbd_pipe_handle sc_bulkin_pipe; /* bulk in pipe */
- usbd_xfer_handle sc_ixfer; /* read request */
- u_char *sc_ibuf; /* read buffer */
u_int sc_ibufsize; /* read buffer size */
u_int sc_ibufsizepad; /* read buffer size padded */
+ struct ucom_buffer sc_ibuff[UCOM_IN_BUFFS];
+ SIMPLEQ_HEAD(, ucom_buffer) sc_ibuff_empty;
+ SIMPLEQ_HEAD(, ucom_buffer) sc_ibuff_full;
int sc_bulkout_no; /* bulk out endpoint address */
usbd_pipe_handle sc_bulkout_pipe;/* bulk out pipe */
- usbd_xfer_handle sc_oxfer; /* write request */
- u_char *sc_obuf; /* write buffer */
u_int sc_obufsize; /* write buffer size */
- u_int sc_opkthdrlen; /* header length of
- * output packet */
+ u_int sc_opkthdrlen; /* header length of */
+ struct ucom_buffer sc_obuff[UCOM_OUT_BUFFS];
+ SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_free;
+ SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_full;
+
+ void *sc_si;
struct ucom_methods *sc_methods;
void *sc_parent;
@@ -117,6 +137,8 @@
u_char sc_lsr;
u_char sc_msr;
u_char sc_mcr;
+ volatile u_char sc_rx_stopped;
+ u_char sc_rx_unblock;
u_char sc_tx_stopped;
int sc_swflags;
@@ -143,21 +165,28 @@
ucomstop, ucomtty, ucompoll, nommap, ttykqfilter, D_TTY
};
-Static void ucom_cleanup(struct ucom_softc *);
-Static void ucom_hwiflow(struct ucom_softc *);
-Static int ucomparam(struct tty *, struct termios *);
-Static void ucomstart(struct tty *);
-Static void ucom_shutdown(struct ucom_softc *);
-Static int ucom_do_ioctl(struct ucom_softc *, u_long, void *,
+static void ucom_cleanup(struct ucom_softc *);
+static int ucomparam(struct tty *, struct termios *);
+static int ucomhwiflow(struct tty *, int);
+static void ucomstart(struct tty *);
+static void ucom_shutdown(struct ucom_softc *);
+static int ucom_do_ioctl(struct ucom_softc *, u_long, void *,
int, struct lwp *);
-Static void ucom_dtr(struct ucom_softc *, int);
-Static void ucom_rts(struct ucom_softc *, int);
-Static void ucom_break(struct ucom_softc *, int);
-Static usbd_status ucomstartread(struct ucom_softc *);
-Static void ucomreadcb(usbd_xfer_handle, usbd_private_handle, usbd_status);
-Static void ucomwritecb(usbd_xfer_handle, usbd_private_handle, usbd_status);
-Static void tiocm_to_ucom(struct ucom_softc *, u_long, int);
-Static int ucom_to_tiocm(struct ucom_softc *);
+static void ucom_dtr(struct ucom_softc *, int);
+static void ucom_rts(struct ucom_softc *, int);
+static void ucom_break(struct ucom_softc *, int);
+static void tiocm_to_ucom(struct ucom_softc *, u_long, int);
+static int ucom_to_tiocm(struct ucom_softc *);
+
+static void ucomreadcb(usbd_xfer_handle, usbd_private_handle, usbd_status);
+static void ucom_submit_write(struct ucom_softc *, struct ucom_buffer *);
+static void ucom_write_status(struct ucom_softc *, struct ucom_buffer *,
+ usbd_status);
+
+static void ucomwritecb(usbd_xfer_handle, usbd_private_handle, usbd_status);
+static void ucom_read_complete(struct ucom_softc *);
+static usbd_status ucomsubmitread(struct ucom_softc *, struct ucom_buffer *);
+static void ucom_softintr(void *);
USB_DECLARE_DRIVER(ucom);
@@ -189,9 +218,21 @@
sc->sc_parent = uca->arg;
sc->sc_portno = uca->portno;
+ sc->sc_lsr = 0;
+ sc->sc_msr = 0;
+ sc->sc_mcr = 0;
+ sc->sc_tx_stopped = 0;
+ sc->sc_swflags = 0;
+ sc->sc_opening = 0;
+ sc->sc_refcnt = 0;
+ sc->sc_dying = 0;
+
+ sc->sc_si = softint_establish(SOFTINT_NET, ucom_softintr, sc);
+
tp = ttymalloc();
tp->t_oproc = ucomstart;
tp->t_param = ucomparam;
+ tp->t_hwiflow = ucomhwiflow;
sc->sc_tty = tp;
DPRINTF(("ucom_attach: tty_attach %p\n", tp));
@@ -212,7 +253,7 @@
struct ucom_softc *sc = device_private(self);
struct tty *tp = sc->sc_tty;
int maj, mn;
- int s;
+ int s, i;
DPRINTF(("ucom_detach: sc=%p flags=%d tp=%p, pipe=%d,%d\n",
sc, flags, tp, sc->sc_bulkin_no, sc->sc_bulkout_no));
@@ -238,6 +279,8 @@
/* Wait for processes to go away. */
usb_detach_wait(USBDEV(sc->sc_dev));
}
+
+ softint_disestablish(sc->sc_si);
splx(s);
/* locate the major number */
@@ -257,6 +300,16 @@
sc->sc_tty = NULL;
}
+ for (i = 0; i < UCOM_IN_BUFFS; i++) {
+ if (sc->sc_ibuff[i].ub_xfer != NULL)
+ usbd_free_xfer(sc->sc_ibuff[i].ub_xfer);
+ }
+
+ for (i = 0; i < UCOM_OUT_BUFFS; i++) {
+ if (sc->sc_obuff[i].ub_xfer != NULL)
+ usbd_free_xfer(sc->sc_obuff[i].ub_xfer);
+ }
+
/* Detach the random source */
#if defined(__NetBSD__) && NRND > 0
rnd_detach_source(&sc->sc_rndsource);
@@ -303,8 +356,9 @@
int unit = UCOMUNIT(dev);
usbd_status err;
struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit);
+ struct ucom_buffer *ub;
struct tty *tp;
- int s;
+ int s, i;
int error;
if (sc == NULL)
@@ -388,15 +442,12 @@
ucom_dtr(sc, 1);
ucom_rts(sc, 1);
- /* XXX CLR(sc->sc_rx_flags, RX_ANY_BLOCK);*/
- ucom_hwiflow(sc);
-
DPRINTF(("ucomopen: open pipes in=%d out=%d\n",
sc->sc_bulkin_no, sc->sc_bulkout_no));
/* Open the bulk pipes */
- err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0,
- &sc->sc_bulkin_pipe);
+ err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no,
+ USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
if (err) {
DPRINTF(("%s: open bulk in error (addr %d), err=%s\n",
USBDEVNAME(sc->sc_dev), sc->sc_bulkin_no,
@@ -414,35 +465,56 @@
goto fail_1;
}
- /* Allocate a request and an input buffer and start reading. */
- sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev);
- if (sc->sc_ixfer == NULL) {
- error = ENOMEM;
- goto fail_2;
- }
+ sc->sc_rx_unblock = 0;
+ sc->sc_rx_stopped = 0;
+ sc->sc_tx_stopped = 0;
+
+ memset(sc->sc_ibuff, 0, sizeof(sc->sc_ibuff));
+ memset(sc->sc_obuff, 0, sizeof(sc->sc_obuff));
+
+ SIMPLEQ_INIT(&sc->sc_ibuff_empty);
+ SIMPLEQ_INIT(&sc->sc_ibuff_full);
+ SIMPLEQ_INIT(&sc->sc_obuff_free);
+ SIMPLEQ_INIT(&sc->sc_obuff_full);
- sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer,
- sc->sc_ibufsizepad);
- if (sc->sc_ibuf == NULL) {
- error = ENOMEM;
- goto fail_3;
+ /* Allocate input buffers */
+ for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
+ ub++) {
+ ub->ub_xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (ub->ub_xfer == NULL) {
+ error = ENOMEM;
+ goto fail_2;
+ }
+ ub->ub_data = usbd_alloc_buffer(ub->ub_xfer,
+ sc->sc_ibufsizepad);
+ if (ub->ub_data == NULL) {
+ error = ENOMEM;
+ goto fail_2;
+ }
+
+ if (ucomsubmitread(sc, ub) != USBD_NORMAL_COMPLETION) {
+ error = EIO;
+ goto fail_2;
+ }
}
- sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev);
- if (sc->sc_oxfer == NULL) {
- error = ENOMEM;
- goto fail_3;
+ for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
+ ub++) {
+ ub->ub_xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (ub->ub_xfer == NULL) {
+ error = ENOMEM;
+ goto fail_2;
+ }
+ ub->ub_data = usbd_alloc_buffer(ub->ub_xfer,
+ sc->sc_obufsize);
+ if (ub->ub_data == NULL) {
+ error = ENOMEM;
+ goto fail_2;
+ }
+
+ SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
}
- sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer,
- sc->sc_obufsize +
- sc->sc_opkthdrlen);
- if (sc->sc_obuf == NULL) {
- error = ENOMEM;
- goto fail_4;
- }
-
- ucomstartread(sc);
}
sc->sc_opening = 0;
wakeup(&sc->sc_opening);
@@ -458,13 +530,24 @@
return (0);
Home |
Main Index |
Thread Index |
Old Index