Fri Aug 23 04:29:28 2019 UTC ()
- 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


(mrg)
diff -r1.22 -r1.23 src/sys/dev/usb/usbnet.c

cvs diff -r1.22 -r1.23 src/sys/dev/usb/usbnet.c (expand / switch to unified diff)

--- src/sys/dev/usb/usbnet.c 2019/08/20 06:37:06 1.22
+++ src/sys/dev/usb/usbnet.c 2019/08/23 04:29:28 1.23
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: usbnet.c,v 1.22 2019/08/20 06:37:06 mrg Exp $ */ 1/* $NetBSD: usbnet.c,v 1.23 2019/08/23 04:29:28 mrg Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2019 Matthew R. Green 4 * Copyright (c) 2019 Matthew R. Green
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -23,43 +23,43 @@ @@ -23,43 +23,43 @@
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE. 28 * SUCH DAMAGE.
29 */ 29 */
30 30
31/* 31/*
32 * Common code shared between USB network drivers. 32 * Common code shared between USB network drivers.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.22 2019/08/20 06:37:06 mrg Exp $"); 36__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.23 2019/08/23 04:29:28 mrg Exp $");
37 37
38#include <sys/param.h> 38#include <sys/param.h>
39#include <sys/kernel.h> 39#include <sys/kernel.h>
40#include <sys/kmem.h> 40#include <sys/kmem.h>
41#include <sys/module.h> 41#include <sys/module.h>
 42#include <sys/atomic.h>
42 43
43#include <dev/usb/usbnet.h> 44#include <dev/usb/usbnet.h>
44#include <dev/usb/usbhist.h> 45#include <dev/usb/usbhist.h>
45 46
46struct usbnet_cdata { 47struct usbnet_cdata {
47 struct usbnet_chain *uncd_tx_chain; 48 struct usbnet_chain *uncd_tx_chain;
48 struct usbnet_chain *uncd_rx_chain; 49 struct usbnet_chain *uncd_rx_chain;
49 50
50 int uncd_tx_prod; 51 int uncd_tx_prod;
51 int uncd_tx_cnt; 52 int uncd_tx_cnt;
52 int uncd_rx_cnt; 
53}; 53};
54 54
55struct usbnet_private { 55struct usbnet_private {
56 /* 56 /*
57 * - unp_lock protects most of the structure, and the public one 57 * - unp_lock protects most of the structure, and the public one
58 * - unp_miilock must be held to access this device's MII bus 58 * - unp_miilock must be held to access this device's MII bus
59 * - unp_rxlock protects the rx path and its data 59 * - unp_rxlock protects the rx path and its data
60 * - unp_txlock protects the tx path and its data 60 * - unp_txlock protects the tx path and its data
61 * - unp_detachcv handles detach vs open references 61 * - unp_detachcv handles detach vs open references
62 */ 62 */
63 kmutex_t unp_lock; 63 kmutex_t unp_lock;
64 kmutex_t unp_miilock; 64 kmutex_t unp_miilock;
65 kmutex_t unp_rxlock; 65 kmutex_t unp_rxlock;
@@ -72,36 +72,39 @@ struct usbnet_private { @@ -72,36 +72,39 @@ struct usbnet_private {
72 struct mii_data unp_mii; 72 struct mii_data unp_mii;
73 struct usb_task unp_ticktask; 73 struct usb_task unp_ticktask;
74 struct callout unp_stat_ch; 74 struct callout unp_stat_ch;
75 struct usbd_pipe *unp_ep[USBNET_ENDPT_MAX]; 75 struct usbd_pipe *unp_ep[USBNET_ENDPT_MAX];
76 76
77 bool unp_dying; 77 bool unp_dying;
78 bool unp_stopping; 78 bool unp_stopping;
79 bool unp_attached; 79 bool unp_attached;
80 bool unp_link; 80 bool unp_link;
81 81
82 int unp_refcnt; 82 int unp_refcnt;
83 int unp_timer; 83 int unp_timer;
84 int unp_if_flags; 84 int unp_if_flags;
 85 unsigned unp_number;
85 86
86 krndsource_t unp_rndsrc; 87 krndsource_t unp_rndsrc;
87 88
88 struct timeval unp_rx_notice; 89 struct timeval unp_rx_notice;
89 struct timeval unp_tx_notice; 90 struct timeval unp_tx_notice;
90 struct timeval unp_intr_notice; 91 struct timeval unp_intr_notice;
91}; 92};
92 93
93#define un_cdata(un) (&(un)->un_pri->unp_cdata) 94#define un_cdata(un) (&(un)->un_pri->unp_cdata)
94 95
 96volatile unsigned usbnet_number;
 97
95static int usbnet_modcmd(modcmd_t, void *); 98static int usbnet_modcmd(modcmd_t, void *);
96 99
97#ifdef USB_DEBUG 100#ifdef USB_DEBUG
98#ifndef USBNET_DEBUG 101#ifndef USBNET_DEBUG
99#define usbnetdebug 0 102#define usbnetdebug 0
100#else 103#else
101static int usbnetdebug = 1; 104static int usbnetdebug = 1;
102 105
103SYSCTL_SETUP(sysctl_hw_usbnet_setup, "sysctl hw.usbnet setup") 106SYSCTL_SETUP(sysctl_hw_usbnet_setup, "sysctl hw.usbnet setup")
104{ 107{
105 int err; 108 int err;
106 const struct sysctlnode *rnode; 109 const struct sysctlnode *rnode;
107 const struct sysctlnode *cnode; 110 const struct sysctlnode *cnode;
@@ -126,26 +129,28 @@ SYSCTL_SETUP(sysctl_hw_usbnet_setup, "sy @@ -126,26 +129,28 @@ SYSCTL_SETUP(sysctl_hw_usbnet_setup, "sy
126fail: 129fail:
127 aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err); 130 aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err);
128} 131}
129 132
130#endif /* USBNET_DEBUG */ 133#endif /* USBNET_DEBUG */
131#endif /* USB_DEBUG */ 134#endif /* USB_DEBUG */
132 135
133#define DPRINTF(FMT,A,B,C,D) USBHIST_LOGN(usbnetdebug,1,FMT,A,B,C,D) 136#define DPRINTF(FMT,A,B,C,D) USBHIST_LOGN(usbnetdebug,1,FMT,A,B,C,D)
134#define DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGN(usbnetdebug,N,FMT,A,B,C,D) 137#define DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGN(usbnetdebug,N,FMT,A,B,C,D)
135#define USBNETHIST_FUNC() USBHIST_FUNC() 138#define USBNETHIST_FUNC() USBHIST_FUNC()
136#define USBNETHIST_CALLED(name) USBHIST_CALLED(usbnetdebug) 139#define USBNETHIST_CALLED(name) USBHIST_CALLED(usbnetdebug)
137#define USBNETHIST_CALLARGS(FMT,A,B,C,D) \ 140#define USBNETHIST_CALLARGS(FMT,A,B,C,D) \
138 USBHIST_CALLARGS(usbnetdebug,FMT,A,B,C,D) 141 USBHIST_CALLARGS(usbnetdebug,FMT,A,B,C,D)
 142#define USBNETHIST_CALLARGSN(N,FMT,A,B,C,D) \
 143 USBHIST_CALLARGSN(usbnetdebug,N,FMT,A,B,C,D)
139 144
140/* Callback vectors. */ 145/* Callback vectors. */
141 146
142static void 147static void
143uno_stop(struct usbnet *un, struct ifnet *ifp, int disable) 148uno_stop(struct usbnet *un, struct ifnet *ifp, int disable)
144{ 149{
145 if (un->un_ops->uno_stop) 150 if (un->un_ops->uno_stop)
146 (*un->un_ops->uno_stop)(ifp, disable); 151 (*un->un_ops->uno_stop)(ifp, disable);
147} 152}
148 153
149static int 154static int
150uno_ioctl(struct usbnet *un, struct ifnet *ifp, u_long cmd, void *data) 155uno_ioctl(struct usbnet *un, struct ifnet *ifp, u_long cmd, void *data)
151{ 156{
@@ -236,86 +241,96 @@ usbnet_newbuf(size_t buflen) @@ -236,86 +241,96 @@ usbnet_newbuf(size_t buflen)
236} 241}
237 242
238/* 243/*
239 * usbnet_rxeof() is designed to be the done callback for rx completion. 244 * usbnet_rxeof() is designed to be the done callback for rx completion.
240 * it provides generic setup and finalisation, calls a different usbnet 245 * it provides generic setup and finalisation, calls a different usbnet
241 * rx_loop callback in the middle, which can use usbnet_enqueue() to 246 * rx_loop callback in the middle, which can use usbnet_enqueue() to
242 * enqueue a packet for higher levels (or usbnet_input() if previously 247 * enqueue a packet for higher levels (or usbnet_input() if previously
243 * using if_input() path.) 248 * using if_input() path.)
244 */ 249 */
245void 250void
246usbnet_enqueue(struct usbnet * const un, uint8_t *buf, size_t buflen, 251usbnet_enqueue(struct usbnet * const un, uint8_t *buf, size_t buflen,
247 int csum_flags, uint32_t csum_data, int mbuf_flags) 252 int csum_flags, uint32_t csum_data, int mbuf_flags)
248{ 253{
249 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 254 USBNETHIST_FUNC();
250 struct ifnet * const ifp = usbnet_ifp(un); 255 struct ifnet * const ifp = usbnet_ifp(un);
 256 struct usbnet_private * const unp __unused = un->un_pri;
251 struct mbuf *m; 257 struct mbuf *m;
252 258
 259 USBNETHIST_CALLARGSN(5, "%d: enter: len=%zu csf %x mbf %x",
 260 unp->unp_number, buflen, csum_flags, mbuf_flags);
 261
253 usbnet_isowned_rx(un); 262 usbnet_isowned_rx(un);
254 263
255 m = usbnet_newbuf(buflen); 264 m = usbnet_newbuf(buflen);
256 if (m == NULL) { 265 if (m == NULL) {
 266 DPRINTF("%d: no memory", unp->unp_number, 0, 0, 0);
257 ifp->if_ierrors++; 267 ifp->if_ierrors++;
258 return; 268 return;
259 } 269 }
260 270
261 m_set_rcvif(m, ifp); 271 m_set_rcvif(m, ifp);
262 m->m_pkthdr.csum_flags = csum_flags; 272 m->m_pkthdr.csum_flags = csum_flags;
263 m->m_pkthdr.csum_data = csum_data; 273 m->m_pkthdr.csum_data = csum_data;
264 m->m_flags |= mbuf_flags; 274 m->m_flags |= mbuf_flags;
265 memcpy(mtod(m, uint8_t *), buf, buflen); 275 memcpy(mtod(m, uint8_t *), buf, buflen);
266 276
267 /* push the packet up */ 277 /* push the packet up */
268 if_percpuq_enqueue(ifp->if_percpuq, m); 278 if_percpuq_enqueue(ifp->if_percpuq, m);
269} 279}
270 280
271void 281void
272usbnet_input(struct usbnet * const un, uint8_t *buf, size_t buflen) 282usbnet_input(struct usbnet * const un, uint8_t *buf, size_t buflen)
273{ 283{
274 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 284 USBNETHIST_FUNC();
275 struct ifnet * const ifp = usbnet_ifp(un); 285 struct ifnet * const ifp = usbnet_ifp(un);
 286 struct usbnet_private * const unp __unused = un->un_pri;
276 struct mbuf *m; 287 struct mbuf *m;
277 288
 289 USBNETHIST_CALLARGSN(5, "%d: enter: buf %jx len %ju",
 290 unp->unp_number, (uintptr_t)buf, buflen, 0);
 291
278 usbnet_isowned_rx(un); 292 usbnet_isowned_rx(un);
279 DPRINTFN(0, "called! un %jx buf %jx len %ju", 
280 (uintmax_t)(uintptr_t)un, (uintmax_t)(uintptr_t)buf, buflen, 0); 
281 293
282 m = usbnet_newbuf(buflen); 294 m = usbnet_newbuf(buflen);
283 if (m == NULL) { 295 if (m == NULL) {
284 ifp->if_ierrors++; 296 ifp->if_ierrors++;
285 return; 297 return;
286 } 298 }
287 299
288 m_set_rcvif(m, ifp); 300 m_set_rcvif(m, ifp);
289 memcpy(mtod(m, char *), buf, buflen); 301 memcpy(mtod(m, char *), buf, buflen);
290 302
291 /* push the packet up */ 303 /* push the packet up */
292 if_input(ifp, m); 304 if_input(ifp, m);
293} 305}
294 306
295/* 307/*
296 * A frame has been uploaded: pass the resulting mbuf chain up to 308 * A frame has been uploaded: pass the resulting mbuf chain up to
297 * the higher level protocols. 309 * the higher level protocols.
298 */ 310 */
299static void 311static void
300usbnet_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 312usbnet_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
301{ 313{
302 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 314 USBNETHIST_FUNC();
303 struct usbnet_chain * const c = priv; 315 struct usbnet_chain * const c = priv;
304 struct usbnet * const un = c->unc_un; 316 struct usbnet * const un = c->unc_un;
305 struct usbnet_private * const unp = un->un_pri; 317 struct usbnet_private * const unp = un->un_pri;
306 struct ifnet * const ifp = usbnet_ifp(un); 318 struct ifnet * const ifp = usbnet_ifp(un);
307 uint32_t total_len; 319 uint32_t total_len;
308 320
 321 USBNETHIST_CALLARGSN(5, "%d: enter: status %x xfer %jx",
 322 unp->unp_number, status, (uintptr_t)xfer, 0);
 323
309 mutex_enter(&unp->unp_rxlock); 324 mutex_enter(&unp->unp_rxlock);
310 325
311 if (unp->unp_dying || unp->unp_stopping || 326 if (unp->unp_dying || unp->unp_stopping ||
312 status == USBD_INVAL || status == USBD_NOT_STARTED || 327 status == USBD_INVAL || status == USBD_NOT_STARTED ||
313 status == USBD_CANCELLED || !(ifp->if_flags & IFF_RUNNING)) 328 status == USBD_CANCELLED || !(ifp->if_flags & IFF_RUNNING))
314 goto out; 329 goto out;
315 330
316 if (status != USBD_NORMAL_COMPLETION) { 331 if (status != USBD_NORMAL_COMPLETION) {
317 if (usbd_ratecheck(&unp->unp_rx_notice)) 332 if (usbd_ratecheck(&unp->unp_rx_notice))
318 aprint_error_dev(un->un_dev, "usb errors on rx: %s\n", 333 aprint_error_dev(un->un_dev, "usb errors on rx: %s\n",
319 usbd_errstr(status)); 334 usbd_errstr(status));
320 if (status == USBD_STALLED) 335 if (status == USBD_STALLED)
321 usbd_clear_endpoint_stall_async(unp->unp_ep[USBNET_ENDPT_RX]); 336 usbd_clear_endpoint_stall_async(unp->unp_ep[USBNET_ENDPT_RX]);
@@ -350,26 +365,29 @@ out: @@ -350,26 +365,29 @@ out:
350 mutex_exit(&unp->unp_rxlock); 365 mutex_exit(&unp->unp_rxlock);
351} 366}
352 367
353static void 368static void
354usbnet_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 369usbnet_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
355{ 370{
356 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 371 USBNETHIST_FUNC(); USBNETHIST_CALLED();
357 struct usbnet_chain * const c = priv; 372 struct usbnet_chain * const c = priv;
358 struct usbnet * const un = c->unc_un; 373 struct usbnet * const un = c->unc_un;
359 struct usbnet_cdata * const cd = un_cdata(un); 374 struct usbnet_cdata * const cd = un_cdata(un);
360 struct usbnet_private * const unp = un->un_pri; 375 struct usbnet_private * const unp = un->un_pri;
361 struct ifnet * const ifp = usbnet_ifp(un); 376 struct ifnet * const ifp = usbnet_ifp(un);
362 377
 378 USBNETHIST_CALLARGSN(5, "%d: enter: status %x xfer %jx",
 379 unp->unp_number, status, (uintptr_t)xfer, 0);
 380
363 mutex_enter(&unp->unp_txlock); 381 mutex_enter(&unp->unp_txlock);
364 if (unp->unp_stopping || unp->unp_dying) { 382 if (unp->unp_stopping || unp->unp_dying) {
365 mutex_exit(&unp->unp_txlock); 383 mutex_exit(&unp->unp_txlock);
366 return; 384 return;
367 } 385 }
368 386
369 KASSERT(cd->uncd_tx_cnt > 0); 387 KASSERT(cd->uncd_tx_cnt > 0);
370 cd->uncd_tx_cnt--; 388 cd->uncd_tx_cnt--;
371 389
372 unp->unp_timer = 0; 390 unp->unp_timer = 0;
373 391
374 switch (status) { 392 switch (status) {
375 case USBD_NOT_STARTED: 393 case USBD_NOT_STARTED:
@@ -433,52 +451,64 @@ usbnet_start_locked(struct ifnet *ifp) @@ -433,52 +451,64 @@ usbnet_start_locked(struct ifnet *ifp)
433 struct mbuf *m; 451 struct mbuf *m;
434 unsigned length; 452 unsigned length;
435 int idx; 453 int idx;
436 454
437 usbnet_isowned_tx(un); 455 usbnet_isowned_tx(un);
438 KASSERT(cd->uncd_tx_cnt <= un->un_tx_list_cnt); 456 KASSERT(cd->uncd_tx_cnt <= un->un_tx_list_cnt);
439 457
440 if (!unp->unp_link || (ifp->if_flags & IFF_RUNNING) == 0) { 458 if (!unp->unp_link || (ifp->if_flags & IFF_RUNNING) == 0) {
441 DPRINTF("start called no link (%x) or running (flags %x)", 459 DPRINTF("start called no link (%x) or running (flags %x)",
442 unp->unp_link, ifp->if_flags, 0, 0); 460 unp->unp_link, ifp->if_flags, 0, 0);
443 return; 461 return;
444 } 462 }
445 463
 464 if (cd->uncd_tx_cnt == un->un_tx_list_cnt) {
 465 DPRINTF("start called, tx busy (%jx == %jx)",
 466 cd->uncd_tx_cnt, un->un_tx_list_cnt, 0, 0);
 467 return;
 468 }
 469
446 idx = cd->uncd_tx_prod; 470 idx = cd->uncd_tx_prod;
447 while (cd->uncd_tx_cnt < un->un_tx_list_cnt) { 471 while (cd->uncd_tx_cnt < un->un_tx_list_cnt) {
448 IFQ_POLL(&ifp->if_snd, m); 472 IFQ_POLL(&ifp->if_snd, m);
449 if (m == NULL) 473 if (m == NULL) {
 474 DPRINTF("start called, queue empty", 0, 0, 0, 0);
450 break; 475 break;
 476 }
451 KASSERT(m->m_pkthdr.len <= un->un_tx_bufsz); 477 KASSERT(m->m_pkthdr.len <= un->un_tx_bufsz);
452 478
453 struct usbnet_chain *c = &cd->uncd_tx_chain[idx]; 479 struct usbnet_chain *c = &cd->uncd_tx_chain[idx];
454 480
455 length = uno_tx_prepare(un, m, c); 481 length = uno_tx_prepare(un, m, c);
456 if (length == 0) { 482 if (length == 0) {
 483 DPRINTF("uno_tx_prepare gave zero length", 0, 0, 0, 0);
457 ifp->if_oerrors++; 484 ifp->if_oerrors++;
458 break; 485 break;
459 } 486 }
460 487
461 if (__predict_false(c->unc_xfer == NULL)) { 488 if (__predict_false(c->unc_xfer == NULL)) {
 489 DPRINTF("unc_xfer is NULL", 0, 0, 0, 0);
462 ifp->if_oerrors++; 490 ifp->if_oerrors++;
463 break; 491 break;
464 } 492 }
465 493
466 usbd_setup_xfer(c->unc_xfer, c, c->unc_buf, length, 494 usbd_setup_xfer(c->unc_xfer, c, c->unc_buf, length,
467 un->un_tx_xfer_flags, 10000, usbnet_txeof); 495 un->un_tx_xfer_flags, 10000, usbnet_txeof);
468 496
469 /* Transmit */ 497 /* Transmit */
470 usbd_status err = usbd_transfer(c->unc_xfer); 498 usbd_status err = usbd_transfer(c->unc_xfer);
471 if (err != USBD_IN_PROGRESS) { 499 if (err != USBD_IN_PROGRESS) {
 500 DPRINTF("usbd_transfer on %jx for %ju bytes: %d",
 501 (uintptr_t)c->unc_buf, length, err, 0);
472 ifp->if_oerrors++; 502 ifp->if_oerrors++;
473 break; 503 break;
474 } 504 }
475 505
476 IFQ_DEQUEUE(&ifp->if_snd, m); 506 IFQ_DEQUEUE(&ifp->if_snd, m);
477 507
478 /* 508 /*
479 * If there's a BPF listener, bounce a copy of this frame 509 * If there's a BPF listener, bounce a copy of this frame
480 * to him. 510 * to him.
481 */ 511 */
482 bpf_mtap(ifp, m, BPF_D_OUT); 512 bpf_mtap(ifp, m, BPF_D_OUT);
483 m_freem(m); 513 m_freem(m);
484 514
@@ -655,26 +685,27 @@ static void @@ -655,26 +685,27 @@ static void
655usbnet_tx_list_fini(struct usbnet * const un) 685usbnet_tx_list_fini(struct usbnet * const un)
656{ 686{
657 struct usbnet_cdata * const cd = un_cdata(un); 687 struct usbnet_cdata * const cd = un_cdata(un);
658 688
659 for (size_t i = 0; i < un->un_tx_list_cnt; i++) { 689 for (size_t i = 0; i < un->un_tx_list_cnt; i++) {
660 struct usbnet_chain *c = &cd->uncd_tx_chain[i]; 690 struct usbnet_chain *c = &cd->uncd_tx_chain[i];
661 691
662 if (c->unc_xfer != NULL) { 692 if (c->unc_xfer != NULL) {
663 usbd_destroy_xfer(c->unc_xfer); 693 usbd_destroy_xfer(c->unc_xfer);
664 c->unc_xfer = NULL; 694 c->unc_xfer = NULL;
665 c->unc_buf = NULL; 695 c->unc_buf = NULL;
666 } 696 }
667 } 697 }
 698 cd->uncd_tx_prod = cd->uncd_tx_cnt = 0;
668} 699}
669 700
670/* End of common TX functions */ 701/* End of common TX functions */
671 702
672/* Endpoint pipe management. */ 703/* Endpoint pipe management. */
673 704
674static void 705static void
675usbnet_ep_close_pipes(struct usbnet * const un) 706usbnet_ep_close_pipes(struct usbnet * const un)
676{ 707{
677 struct usbnet_private * const unp = un->un_pri; 708 struct usbnet_private * const unp = un->un_pri;
678 709
679 for (size_t i = 0; i < __arraycount(unp->unp_ep); i++) { 710 for (size_t i = 0; i < __arraycount(unp->unp_ep); i++) {
680 if (unp->unp_ep[i] == NULL) 711 if (unp->unp_ep[i] == NULL)
@@ -966,30 +997,34 @@ usbnet_ifflags_cb(struct ethercom *ec) @@ -966,30 +997,34 @@ usbnet_ifflags_cb(struct ethercom *ec)
966 rv = ENETRESET; 997 rv = ENETRESET;
967 } else { 998 } else {
968 rv = ENETRESET; 999 rv = ENETRESET;
969 } 1000 }
970 1001
971 mutex_exit(&unp->unp_lock); 1002 mutex_exit(&unp->unp_lock);
972 1003
973 return rv; 1004 return rv;
974} 1005}
975 1006
976static int 1007static int
977usbnet_ioctl(struct ifnet *ifp, u_long cmd, void *data) 1008usbnet_ioctl(struct ifnet *ifp, u_long cmd, void *data)
978{ 1009{
979 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 1010 USBNETHIST_FUNC();
980 struct usbnet * const un = ifp->if_softc; 1011 struct usbnet * const un = ifp->if_softc;
 1012 struct usbnet_private * const unp __unused = un->un_pri;
981 int error; 1013 int error;
982 1014
 1015 USBNETHIST_CALLARGSN(11, "%d: enter %jx data %x",
 1016 unp->unp_number, cmd, (uintptr_t)data, 0);
 1017
983 if (un->un_ops->uno_override_ioctl) 1018 if (un->un_ops->uno_override_ioctl)
984 return uno_override_ioctl(un, ifp, cmd, data); 1019 return uno_override_ioctl(un, ifp, cmd, data);
985 1020
986 error = ether_ioctl(ifp, cmd, data); 1021 error = ether_ioctl(ifp, cmd, data);
987 if (error == ENETRESET) 1022 if (error == ENETRESET)
988 error = uno_ioctl(un, ifp, cmd, data); 1023 error = uno_ioctl(un, ifp, cmd, data);
989 1024
990 return error; 1025 return error;
991} 1026}
992 1027
993/* 1028/*
994 * Generic stop network function: 1029 * Generic stop network function:
995 * - mark as stopping 1030 * - mark as stopping
@@ -1067,49 +1102,52 @@ usbnet_tick(void *arg) @@ -1067,49 +1102,52 @@ usbnet_tick(void *arg)
1067 struct usbnet_private * const unp = un->un_pri; 1102 struct usbnet_private * const unp = un->un_pri;
1068 1103
1069 mutex_enter(&unp->unp_lock); 1104 mutex_enter(&unp->unp_lock);
1070 if (!unp->unp_stopping && !unp->unp_dying) { 1105 if (!unp->unp_stopping && !unp->unp_dying) {
1071 /* Perform periodic stuff in process context */ 1106 /* Perform periodic stuff in process context */
1072 usb_add_task(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER); 1107 usb_add_task(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER);
1073 } 1108 }
1074 mutex_exit(&unp->unp_lock); 1109 mutex_exit(&unp->unp_lock);
1075} 1110}
1076 1111
1077static void 1112static void
1078usbnet_watchdog(struct ifnet *ifp) 1113usbnet_watchdog(struct ifnet *ifp)
1079{ 1114{
 1115 USBNETHIST_FUNC(); USBNETHIST_CALLED();
1080 struct usbnet * const un = ifp->if_softc; 1116 struct usbnet * const un = ifp->if_softc;
1081 struct usbnet_private * const unp = un->un_pri; 1117 struct usbnet_private * const unp = un->un_pri;
1082 struct usbnet_cdata * const cd = un_cdata(un); 1118 struct usbnet_cdata * const cd = un_cdata(un);
1083 usbd_status err; 1119 usbd_status err;
1084 1120
1085 ifp->if_oerrors++; 1121 ifp->if_oerrors++;
1086 aprint_error_dev(un->un_dev, "watchdog timeout\n"); 1122 aprint_error_dev(un->un_dev, "watchdog timeout\n");
1087 1123
1088 if (cd->uncd_tx_cnt > 0) { 1124 if (cd->uncd_tx_cnt > 0) {
 1125 DPRINTF("uncd_tx_cnt=%u non zero, aborting pipe", 0, 0, 0, 0);
1089 err = usbd_abort_pipe(unp->unp_ep[USBNET_ENDPT_TX]); 1126 err = usbd_abort_pipe(unp->unp_ep[USBNET_ENDPT_TX]);
1090 if (err) 1127 if (err)
1091 aprint_error_dev(un->un_dev, "pipe abort failed: %s\n", 1128 aprint_error_dev(un->un_dev, "pipe abort failed: %s\n",
1092 usbd_errstr(err)); 1129 usbd_errstr(err));
 1130 if (cd->uncd_tx_cnt != 0)
 1131 DPRINTF("uncd_tx_cnt now %u", cd->uncd_tx_cnt, 0, 0, 0);
1093 } 1132 }
1094 1133
1095 if (!IFQ_IS_EMPTY(&ifp->if_snd)) 1134 if (!IFQ_IS_EMPTY(&ifp->if_snd))
1096 (*ifp->if_start)(ifp); 1135 (*ifp->if_start)(ifp);
1097} 1136}
1098 1137
1099static void 1138static void
1100usbnet_tick_task(void *arg) 1139usbnet_tick_task(void *arg)
1101{ 1140{
1102 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 
1103 struct usbnet * const un = arg; 1141 struct usbnet * const un = arg;
1104 struct usbnet_private * const unp = un->un_pri; 1142 struct usbnet_private * const unp = un->un_pri;
1105 1143
1106 mutex_enter(&unp->unp_lock); 1144 mutex_enter(&unp->unp_lock);
1107 if (unp->unp_stopping || unp->unp_dying) { 1145 if (unp->unp_stopping || unp->unp_dying) {
1108 mutex_exit(&unp->unp_lock); 1146 mutex_exit(&unp->unp_lock);
1109 return; 1147 return;
1110 } 1148 }
1111 1149
1112 struct ifnet * const ifp = usbnet_ifp(un); 1150 struct ifnet * const ifp = usbnet_ifp(un);
1113 struct mii_data * const mii = usbnet_mii(un); 1151 struct mii_data * const mii = usbnet_mii(un);
1114 1152
1115 unp->unp_refcnt++; 1153 unp->unp_refcnt++;
@@ -1310,26 +1348,28 @@ usbnet_attach(struct usbnet *un, @@ -1310,26 +1348,28 @@ usbnet_attach(struct usbnet *un,
1310 1348
1311 mutex_init(&unp->unp_miilock, MUTEX_DEFAULT, IPL_NONE); 1349 mutex_init(&unp->unp_miilock, MUTEX_DEFAULT, IPL_NONE);
1312 mutex_init(&unp->unp_txlock, MUTEX_DEFAULT, IPL_SOFTUSB); 1350 mutex_init(&unp->unp_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
1313 mutex_init(&unp->unp_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB); 1351 mutex_init(&unp->unp_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB);
1314 mutex_init(&unp->unp_lock, MUTEX_DEFAULT, IPL_NONE); 1352 mutex_init(&unp->unp_lock, MUTEX_DEFAULT, IPL_NONE);
1315 cv_init(&unp->unp_detachcv, detname); 1353 cv_init(&unp->unp_detachcv, detname);
1316 1354
1317 rnd_attach_source(&unp->unp_rndsrc, device_xname(un->un_dev), 1355 rnd_attach_source(&unp->unp_rndsrc, device_xname(un->un_dev),
1318 RND_TYPE_NET, RND_FLAG_DEFAULT); 1356 RND_TYPE_NET, RND_FLAG_DEFAULT);
1319 1357
1320 usbnet_rx_list_alloc(un); 1358 usbnet_rx_list_alloc(un);
1321 usbnet_tx_list_alloc(un); 1359 usbnet_tx_list_alloc(un);
1322 1360
 1361 unp->unp_number = atomic_inc_uint_nv(&usbnet_number);
 1362
1323 unp->unp_attached = true; 1363 unp->unp_attached = true;
1324} 1364}
1325 1365
1326static void 1366static void
1327usbnet_attach_mii(struct usbnet *un, const struct usbnet_mii *unm) 1367usbnet_attach_mii(struct usbnet *un, const struct usbnet_mii *unm)
1328{ 1368{
1329 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 1369 USBNETHIST_FUNC(); USBNETHIST_CALLED();
1330 struct usbnet_private * const unp = un->un_pri; 1370 struct usbnet_private * const unp = un->un_pri;
1331 struct mii_data * const mii = &unp->unp_mii; 1371 struct mii_data * const mii = &unp->unp_mii;
1332 struct ifnet * const ifp = usbnet_ifp(un); 1372 struct ifnet * const ifp = usbnet_ifp(un);
1333 1373
1334 KASSERT(un->un_ops->uno_read_reg); 1374 KASSERT(un->un_ops->uno_read_reg);
1335 KASSERT(un->un_ops->uno_write_reg); 1375 KASSERT(un->un_ops->uno_write_reg);