summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2007-02-24 21:57:28 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2007-02-24 21:57:28 +0000
commitdcd19487853902ec0b660616978d61649c6ea628 (patch)
tree95d5182f1c79d741a20f229160b87f49862be952 /sys
parent80f4cc9e8fb52b24d1df717112392b05351c1442 (diff)
Add myself to copyright since I took the skeleton driver and made it complete.
Work around a transmit hang problem by setting a delay on transmitting back-to-back packets. Count dropped packets as input errors. Abort pipe if a watchdog occurs to clean up state better.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/if_cdcef.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/sys/dev/usb/if_cdcef.c b/sys/dev/usb/if_cdcef.c
index 9fbadb37854..8bb8b0822ee 100644
--- a/sys/dev/usb/if_cdcef.c
+++ b/sys/dev/usb/if_cdcef.c
@@ -1,6 +1,7 @@
-/* $OpenBSD: if_cdcef.c,v 1.8 2007/02/23 06:10:08 drahn Exp $ */
+/* $OpenBSD: if_cdcef.c,v 1.9 2007/02/24 21:57:27 drahn Exp $ */
/*
+ * Copyright (c) 2007 Dale Rahn <drahn@openbsd.org>
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -69,6 +70,8 @@ struct cdcef_softc {
void *sc_buffer_in;
void *sc_buffer_out;
+ struct timeout start_to;
+
struct mbuf *sc_xmit_mbuf;
struct arpcom sc_arpcom;
@@ -98,6 +101,7 @@ void cdcef_init(struct cdcef_softc *);
void cdcef_stop(struct cdcef_softc *);
int cdcef_encap(struct cdcef_softc *sc, struct mbuf *m, int idx);
struct mbuf * cdcef_newbuf(void);
+void cdcef_start_timeout (void *);
struct cfattach cdcef_ca = {
sizeof(struct cdcef_softc), cdcef_match, cdcef_attach
@@ -154,6 +158,9 @@ USB_ATTACH(cdcef)
/* Fill in the fields needed by the parent device. */
sc->sc_dev.methods = &cdcef_methods;
+ /* timeout to start delayed tranfers */
+ timeout_set(&sc->start_to, cdcef_start_timeout, sc);
+
/*
* Build descriptors according to the device class specification.
*/
@@ -336,11 +343,23 @@ cdcef_txeof(usbf_xfer_handle xfer, usbf_private_handle priv,
ifp->if_opackets++;
if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
- cdcef_start(ifp);
+ timeout_add(&sc->start_to, 1); /* XXX */
+
+ splx(s);
+}
+void
+cdcef_start_timeout (void *v)
+{
+ struct cdcef_softc *sc = v;
+ struct ifnet *ifp = GET_IFP(sc);
+ int s;
+ s = splnet();
+ cdcef_start(ifp);
splx(s);
}
+
void
cdcef_rxeof(usbf_xfer_handle xfer, usbf_private_handle priv,
usbf_status status)
@@ -397,10 +416,10 @@ cdcef_rxeof(usbf_xfer_handle xfer, usbf_private_handle priv,
m = cdcef_newbuf();
if (m == NULL) {
/* message? */
+ ifp->if_ierrors++;
goto done1;
}
- /* XXX - buffer big enough? */
m->m_pkthdr.len = m->m_len = total_len;
bcopy(sc->sc_buffer_out, mtod(m, char *), total_len);
m->m_pkthdr.rcvif = ifp;
@@ -514,6 +533,7 @@ void
cdcef_watchdog(struct ifnet *ifp)
{
struct cdcef_softc *sc = ifp->if_softc;
+ int s;
#if 0
if (sc->sc_dying)
@@ -523,15 +543,13 @@ cdcef_watchdog(struct ifnet *ifp)
ifp->if_oerrors++;
printf("%s: watchdog timeout\n", DEVNAME(sc));
+ s = splusb();
ifp->if_timer = 0;
ifp->if_flags &= ~IFF_OACTIVE;
/* cancel recieve pipe? */
-
- if (sc->sc_xmit_mbuf != NULL) {
- m_freem(sc->sc_xmit_mbuf);
- sc->sc_xmit_mbuf = NULL;
- }
+ usbf_abort_pipe(sc->sc_pipe_in); /* in is tx pipe */
+ splx(s);
}
void