Module Name: src Committed By: mrg Date: Fri Aug 23 04:29:28 UTC 2019
Modified Files: src/sys/dev/usb: usbnet.c Log Message: - remove unused uncd_rx_cnt - add USBNETHIST_CALLARGSN and use it in many places - add more history logs - add a log if watchdog abort leaves uncd_tx_cnt non zero - add a unique (32-bit) number for a each usbnet device and use it for logging - explicitly check for full tx ring in usbnet_start_locked() and return early, which avoids setting the 5 second timer and triggering a watchdog - reset uncd_tx_prod and uncd_tx_cnt to zero in stop To generate a diff of this commit: cvs rdiff -u -r1.22 -r1.23 src/sys/dev/usb/usbnet.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/usbnet.c diff -u src/sys/dev/usb/usbnet.c:1.22 src/sys/dev/usb/usbnet.c:1.23 --- src/sys/dev/usb/usbnet.c:1.22 Tue Aug 20 06:37:06 2019 +++ src/sys/dev/usb/usbnet.c Fri Aug 23 04:29:28 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: usbnet.c,v 1.22 2019/08/20 06:37:06 mrg Exp $ */ +/* $NetBSD: usbnet.c,v 1.23 2019/08/23 04:29:28 mrg Exp $ */ /* * Copyright (c) 2019 Matthew R. Green @@ -33,12 +33,13 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.22 2019/08/20 06:37:06 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.23 2019/08/23 04:29:28 mrg Exp $"); #include <sys/param.h> #include <sys/kernel.h> #include <sys/kmem.h> #include <sys/module.h> +#include <sys/atomic.h> #include <dev/usb/usbnet.h> #include <dev/usb/usbhist.h> @@ -49,7 +50,6 @@ struct usbnet_cdata { int uncd_tx_prod; int uncd_tx_cnt; - int uncd_rx_cnt; }; struct usbnet_private { @@ -82,6 +82,7 @@ struct usbnet_private { int unp_refcnt; int unp_timer; int unp_if_flags; + unsigned unp_number; krndsource_t unp_rndsrc; @@ -92,6 +93,8 @@ struct usbnet_private { #define un_cdata(un) (&(un)->un_pri->unp_cdata) +volatile unsigned usbnet_number; + static int usbnet_modcmd(modcmd_t, void *); #ifdef USB_DEBUG @@ -136,6 +139,8 @@ fail: #define USBNETHIST_CALLED(name) USBHIST_CALLED(usbnetdebug) #define USBNETHIST_CALLARGS(FMT,A,B,C,D) \ USBHIST_CALLARGS(usbnetdebug,FMT,A,B,C,D) +#define USBNETHIST_CALLARGSN(N,FMT,A,B,C,D) \ + USBHIST_CALLARGSN(usbnetdebug,N,FMT,A,B,C,D) /* Callback vectors. */ @@ -246,14 +251,19 @@ void usbnet_enqueue(struct usbnet * const un, uint8_t *buf, size_t buflen, int csum_flags, uint32_t csum_data, int mbuf_flags) { - USBNETHIST_FUNC(); USBNETHIST_CALLED(); + USBNETHIST_FUNC(); struct ifnet * const ifp = usbnet_ifp(un); + struct usbnet_private * const unp __unused = un->un_pri; struct mbuf *m; + USBNETHIST_CALLARGSN(5, "%d: enter: len=%zu csf %x mbf %x", + unp->unp_number, buflen, csum_flags, mbuf_flags); + usbnet_isowned_rx(un); m = usbnet_newbuf(buflen); if (m == NULL) { + DPRINTF("%d: no memory", unp->unp_number, 0, 0, 0); ifp->if_ierrors++; return; } @@ -271,13 +281,15 @@ usbnet_enqueue(struct usbnet * const un, void usbnet_input(struct usbnet * const un, uint8_t *buf, size_t buflen) { - USBNETHIST_FUNC(); USBNETHIST_CALLED(); + USBNETHIST_FUNC(); struct ifnet * const ifp = usbnet_ifp(un); + struct usbnet_private * const unp __unused = un->un_pri; struct mbuf *m; + USBNETHIST_CALLARGSN(5, "%d: enter: buf %jx len %ju", + unp->unp_number, (uintptr_t)buf, buflen, 0); + usbnet_isowned_rx(un); - DPRINTFN(0, "called! un %jx buf %jx len %ju", - (uintmax_t)(uintptr_t)un, (uintmax_t)(uintptr_t)buf, buflen, 0); m = usbnet_newbuf(buflen); if (m == NULL) { @@ -299,13 +311,16 @@ usbnet_input(struct usbnet * const un, u static void usbnet_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) { - USBNETHIST_FUNC(); USBNETHIST_CALLED(); + USBNETHIST_FUNC(); struct usbnet_chain * const c = priv; struct usbnet * const un = c->unc_un; struct usbnet_private * const unp = un->un_pri; struct ifnet * const ifp = usbnet_ifp(un); uint32_t total_len; + USBNETHIST_CALLARGSN(5, "%d: enter: status %x xfer %jx", + unp->unp_number, status, (uintptr_t)xfer, 0); + mutex_enter(&unp->unp_rxlock); if (unp->unp_dying || unp->unp_stopping || @@ -360,6 +375,9 @@ usbnet_txeof(struct usbd_xfer *xfer, voi struct usbnet_private * const unp = un->un_pri; struct ifnet * const ifp = usbnet_ifp(un); + USBNETHIST_CALLARGSN(5, "%d: enter: status %x xfer %jx", + unp->unp_number, status, (uintptr_t)xfer, 0); + mutex_enter(&unp->unp_txlock); if (unp->unp_stopping || unp->unp_dying) { mutex_exit(&unp->unp_txlock); @@ -443,22 +461,32 @@ usbnet_start_locked(struct ifnet *ifp) return; } + if (cd->uncd_tx_cnt == un->un_tx_list_cnt) { + DPRINTF("start called, tx busy (%jx == %jx)", + cd->uncd_tx_cnt, un->un_tx_list_cnt, 0, 0); + return; + } + idx = cd->uncd_tx_prod; while (cd->uncd_tx_cnt < un->un_tx_list_cnt) { IFQ_POLL(&ifp->if_snd, m); - if (m == NULL) + if (m == NULL) { + DPRINTF("start called, queue empty", 0, 0, 0, 0); break; + } KASSERT(m->m_pkthdr.len <= un->un_tx_bufsz); struct usbnet_chain *c = &cd->uncd_tx_chain[idx]; length = uno_tx_prepare(un, m, c); if (length == 0) { + DPRINTF("uno_tx_prepare gave zero length", 0, 0, 0, 0); ifp->if_oerrors++; break; } if (__predict_false(c->unc_xfer == NULL)) { + DPRINTF("unc_xfer is NULL", 0, 0, 0, 0); ifp->if_oerrors++; break; } @@ -469,6 +497,8 @@ usbnet_start_locked(struct ifnet *ifp) /* Transmit */ usbd_status err = usbd_transfer(c->unc_xfer); if (err != USBD_IN_PROGRESS) { + DPRINTF("usbd_transfer on %jx for %ju bytes: %d", + (uintptr_t)c->unc_buf, length, err, 0); ifp->if_oerrors++; break; } @@ -665,6 +695,7 @@ usbnet_tx_list_fini(struct usbnet * cons c->unc_buf = NULL; } } + cd->uncd_tx_prod = cd->uncd_tx_cnt = 0; } /* End of common TX functions */ @@ -976,10 +1007,14 @@ usbnet_ifflags_cb(struct ethercom *ec) static int usbnet_ioctl(struct ifnet *ifp, u_long cmd, void *data) { - USBNETHIST_FUNC(); USBNETHIST_CALLED(); + USBNETHIST_FUNC(); struct usbnet * const un = ifp->if_softc; + struct usbnet_private * const unp __unused = un->un_pri; int error; + USBNETHIST_CALLARGSN(11, "%d: enter %jx data %x", + unp->unp_number, cmd, (uintptr_t)data, 0); + if (un->un_ops->uno_override_ioctl) return uno_override_ioctl(un, ifp, cmd, data); @@ -1077,6 +1112,7 @@ usbnet_tick(void *arg) static void usbnet_watchdog(struct ifnet *ifp) { + USBNETHIST_FUNC(); USBNETHIST_CALLED(); struct usbnet * const un = ifp->if_softc; struct usbnet_private * const unp = un->un_pri; struct usbnet_cdata * const cd = un_cdata(un); @@ -1086,10 +1122,13 @@ usbnet_watchdog(struct ifnet *ifp) aprint_error_dev(un->un_dev, "watchdog timeout\n"); if (cd->uncd_tx_cnt > 0) { + DPRINTF("uncd_tx_cnt=%u non zero, aborting pipe", 0, 0, 0, 0); err = usbd_abort_pipe(unp->unp_ep[USBNET_ENDPT_TX]); if (err) aprint_error_dev(un->un_dev, "pipe abort failed: %s\n", usbd_errstr(err)); + if (cd->uncd_tx_cnt != 0) + DPRINTF("uncd_tx_cnt now %u", cd->uncd_tx_cnt, 0, 0, 0); } if (!IFQ_IS_EMPTY(&ifp->if_snd)) @@ -1099,7 +1138,6 @@ usbnet_watchdog(struct ifnet *ifp) static void usbnet_tick_task(void *arg) { - USBNETHIST_FUNC(); USBNETHIST_CALLED(); struct usbnet * const un = arg; struct usbnet_private * const unp = un->un_pri; @@ -1320,6 +1358,8 @@ usbnet_attach(struct usbnet *un, usbnet_rx_list_alloc(un); usbnet_tx_list_alloc(un); + unp->unp_number = atomic_inc_uint_nv(&usbnet_number); + unp->unp_attached = true; }