Thu Mar 3 05:50:40 2022 UTC ()
usbnet: Use atomic_load/store_relaxed for unp_dying.

This way we don't need to hold the core lock to avoid upsetting
sanitizers (which probably find the current code upsetting), and we
can use it to exit early from timeout loops that run under the core
lock (which is probably not necessary for them to do anyway, but
let's worry about that later).


(riastradh)
diff -r1.72 -r1.73 src/sys/dev/usb/usbnet.c

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

--- src/sys/dev/usb/usbnet.c 2022/03/03 05:50:31 1.72
+++ src/sys/dev/usb/usbnet.c 2022/03/03 05:50:39 1.73
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: usbnet.c,v 1.72 2022/03/03 05:50:31 riastradh Exp $ */ 1/* $NetBSD: usbnet.c,v 1.73 2022/03/03 05:50:39 riastradh 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.
@@ -21,27 +21,27 @@ @@ -21,27 +21,27 @@
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * Common code shared between USB network drivers. 30 * Common code shared between USB network drivers.
31 */ 31 */
32 32
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.72 2022/03/03 05:50:31 riastradh Exp $"); 34__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.73 2022/03/03 05:50:39 riastradh Exp $");
35 35
36#include <sys/param.h> 36#include <sys/param.h>
37#include <sys/kernel.h> 37#include <sys/kernel.h>
38#include <sys/kmem.h> 38#include <sys/kmem.h>
39#include <sys/module.h> 39#include <sys/module.h>
40#include <sys/atomic.h> 40#include <sys/atomic.h>
41 41
42#include <dev/usb/usbnet.h> 42#include <dev/usb/usbnet.h>
43#include <dev/usb/usbhist.h> 43#include <dev/usb/usbhist.h>
44 44
45struct usbnet_cdata { 45struct usbnet_cdata {
46 struct usbnet_chain *uncd_tx_chain; 46 struct usbnet_chain *uncd_tx_chain;
47 struct usbnet_chain *uncd_rx_chain; 47 struct usbnet_chain *uncd_rx_chain;
@@ -67,27 +67,27 @@ struct usbnet_private { @@ -67,27 +67,27 @@ struct usbnet_private {
67 kmutex_t unp_rxlock; 67 kmutex_t unp_rxlock;
68 kmutex_t unp_txlock; 68 kmutex_t unp_txlock;
69 kcondvar_t unp_detachcv; 69 kcondvar_t unp_detachcv;
70 70
71 struct usbnet_cdata unp_cdata; 71 struct usbnet_cdata unp_cdata;
72 72
73 struct ethercom unp_ec; 73 struct ethercom unp_ec;
74 struct mii_data unp_mii; 74 struct mii_data unp_mii;
75 struct usb_task unp_mcasttask; 75 struct usb_task unp_mcasttask;
76 struct usb_task unp_ticktask; 76 struct usb_task unp_ticktask;
77 struct callout unp_stat_ch; 77 struct callout unp_stat_ch;
78 struct usbd_pipe *unp_ep[USBNET_ENDPT_MAX]; 78 struct usbd_pipe *unp_ep[USBNET_ENDPT_MAX];
79 79
80 bool unp_dying; 80 volatile bool unp_dying;
81 bool unp_stopping; 81 bool unp_stopping;
82 bool unp_attached; 82 bool unp_attached;
83 bool unp_ifp_attached; 83 bool unp_ifp_attached;
84 bool unp_link; 84 bool unp_link;
85 85
86 int unp_refcnt; 86 int unp_refcnt;
87 int unp_timer; 87 int unp_timer;
88 unsigned short unp_if_flags; 88 unsigned short unp_if_flags;
89 unsigned unp_number; 89 unsigned unp_number;
90 90
91 krndsource_t unp_rndsrc; 91 krndsource_t unp_rndsrc;
92 92
93 struct timeval unp_rx_notice; 93 struct timeval unp_rx_notice;
@@ -346,54 +346,54 @@ static void @@ -346,54 +346,54 @@ static void
346usbnet_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 346usbnet_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
347{ 347{
348 USBNETHIST_FUNC(); 348 USBNETHIST_FUNC();
349 struct usbnet_chain * const c = priv; 349 struct usbnet_chain * const c = priv;
350 struct usbnet * const un = c->unc_un; 350 struct usbnet * const un = c->unc_un;
351 struct usbnet_private * const unp = un->un_pri; 351 struct usbnet_private * const unp = un->un_pri;
352 uint32_t total_len; 352 uint32_t total_len;
353 353
354 USBNETHIST_CALLARGSN(5, "%jd: enter: status %#jx xfer %#jx", 354 USBNETHIST_CALLARGSN(5, "%jd: enter: status %#jx xfer %#jx",
355 unp->unp_number, status, (uintptr_t)xfer, 0); 355 unp->unp_number, status, (uintptr_t)xfer, 0);
356 356
357 mutex_enter(&unp->unp_rxlock); 357 mutex_enter(&unp->unp_rxlock);
358 358
359 if (unp->unp_dying || unp->unp_stopping || 359 if (usbnet_isdying(un) || unp->unp_stopping ||
360 status == USBD_INVAL || status == USBD_NOT_STARTED || 360 status == USBD_INVAL || status == USBD_NOT_STARTED ||
361 status == USBD_CANCELLED) 361 status == USBD_CANCELLED)
362 goto out; 362 goto out;
363 363
364 if (status != USBD_NORMAL_COMPLETION) { 364 if (status != USBD_NORMAL_COMPLETION) {
365 if (usbd_ratecheck(&unp->unp_rx_notice)) 365 if (usbd_ratecheck(&unp->unp_rx_notice))
366 device_printf(un->un_dev, "usb errors on rx: %s\n", 366 device_printf(un->un_dev, "usb errors on rx: %s\n",
367 usbd_errstr(status)); 367 usbd_errstr(status));
368 if (status == USBD_STALLED) 368 if (status == USBD_STALLED)
369 usbd_clear_endpoint_stall_async(unp->unp_ep[USBNET_ENDPT_RX]); 369 usbd_clear_endpoint_stall_async(unp->unp_ep[USBNET_ENDPT_RX]);
370 goto done; 370 goto done;
371 } 371 }
372 372
373 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 373 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
374 374
375 if (total_len > un->un_rx_bufsz) { 375 if (total_len > un->un_rx_bufsz) {
376 aprint_error_dev(un->un_dev, 376 aprint_error_dev(un->un_dev,
377 "rxeof: too large transfer (%u > %u)\n", 377 "rxeof: too large transfer (%u > %u)\n",
378 total_len, un->un_rx_bufsz); 378 total_len, un->un_rx_bufsz);
379 goto done; 379 goto done;
380 } 380 }
381 381
382 uno_rx_loop(un, c, total_len); 382 uno_rx_loop(un, c, total_len);
383 usbnet_isowned_rx(un); 383 usbnet_isowned_rx(un);
384 384
385done: 385done:
386 if (unp->unp_dying || unp->unp_stopping) 386 if (usbnet_isdying(un) || unp->unp_stopping)
387 goto out; 387 goto out;
388 388
389 mutex_exit(&unp->unp_rxlock); 389 mutex_exit(&unp->unp_rxlock);
390 390
391 /* Setup new transfer. */ 391 /* Setup new transfer. */
392 usbd_setup_xfer(xfer, c, c->unc_buf, un->un_rx_bufsz, 392 usbd_setup_xfer(xfer, c, c->unc_buf, un->un_rx_bufsz,
393 un->un_rx_xfer_flags, USBD_NO_TIMEOUT, usbnet_rxeof); 393 un->un_rx_xfer_flags, USBD_NO_TIMEOUT, usbnet_rxeof);
394 usbd_transfer(xfer); 394 usbd_transfer(xfer);
395 return; 395 return;
396 396
397out: 397out:
398 mutex_exit(&unp->unp_rxlock); 398 mutex_exit(&unp->unp_rxlock);
399} 399}
@@ -402,27 +402,27 @@ static void @@ -402,27 +402,27 @@ static void
402usbnet_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 402usbnet_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
403{ 403{
404 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 404 USBNETHIST_FUNC(); USBNETHIST_CALLED();
405 struct usbnet_chain * const c = priv; 405 struct usbnet_chain * const c = priv;
406 struct usbnet * const un = c->unc_un; 406 struct usbnet * const un = c->unc_un;
407 struct usbnet_cdata * const cd = un_cdata(un); 407 struct usbnet_cdata * const cd = un_cdata(un);
408 struct usbnet_private * const unp = un->un_pri; 408 struct usbnet_private * const unp = un->un_pri;
409 struct ifnet * const ifp = usbnet_ifp(un); 409 struct ifnet * const ifp = usbnet_ifp(un);
410 410
411 USBNETHIST_CALLARGSN(5, "%jd: enter: status %#jx xfer %#jx", 411 USBNETHIST_CALLARGSN(5, "%jd: enter: status %#jx xfer %#jx",
412 unp->unp_number, status, (uintptr_t)xfer, 0); 412 unp->unp_number, status, (uintptr_t)xfer, 0);
413 413
414 mutex_enter(&unp->unp_txlock); 414 mutex_enter(&unp->unp_txlock);
415 if (unp->unp_stopping || unp->unp_dying) { 415 if (unp->unp_stopping || usbnet_isdying(un)) {
416 mutex_exit(&unp->unp_txlock); 416 mutex_exit(&unp->unp_txlock);
417 return; 417 return;
418 } 418 }
419 419
420 KASSERT(cd->uncd_tx_cnt > 0); 420 KASSERT(cd->uncd_tx_cnt > 0);
421 cd->uncd_tx_cnt--; 421 cd->uncd_tx_cnt--;
422 422
423 unp->unp_timer = 0; 423 unp->unp_timer = 0;
424 424
425 switch (status) { 425 switch (status) {
426 case USBD_NOT_STARTED: 426 case USBD_NOT_STARTED:
427 case USBD_CANCELLED: 427 case USBD_CANCELLED:
428 break; 428 break;
@@ -446,32 +446,32 @@ usbnet_txeof(struct usbd_xfer *xfer, voi @@ -446,32 +446,32 @@ usbnet_txeof(struct usbd_xfer *xfer, voi
446 446
447 if (status == USBD_NORMAL_COMPLETION && !IFQ_IS_EMPTY(&ifp->if_snd)) 447 if (status == USBD_NORMAL_COMPLETION && !IFQ_IS_EMPTY(&ifp->if_snd))
448 (*ifp->if_start)(ifp); 448 (*ifp->if_start)(ifp);
449} 449}
450 450
451static void 451static void
452usbnet_pipe_intr(struct usbd_xfer *xfer, void *priv, usbd_status status) 452usbnet_pipe_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
453{ 453{
454 USBNETHIST_FUNC(); 454 USBNETHIST_FUNC();
455 struct usbnet * const un = priv; 455 struct usbnet * const un = priv;
456 struct usbnet_private * const unp = un->un_pri; 456 struct usbnet_private * const unp = un->un_pri;
457 struct usbnet_intr * const uni = un->un_intr; 457 struct usbnet_intr * const uni = un->un_intr;
458 458
459 if (uni == NULL || unp->unp_dying || unp->unp_stopping || 459 if (uni == NULL || usbnet_isdying(un) || unp->unp_stopping ||
460 status == USBD_INVAL || status == USBD_NOT_STARTED || 460 status == USBD_INVAL || status == USBD_NOT_STARTED ||
461 status == USBD_CANCELLED) { 461 status == USBD_CANCELLED) {
462 USBNETHIST_CALLARGS("%jd: uni %#jx d/s %#jx status %#jx", 462 USBNETHIST_CALLARGS("%jd: uni %#jx d/s %#jx status %#jx",
463 unp->unp_number, (uintptr_t)uni, 463 unp->unp_number, (uintptr_t)uni,
464 (unp->unp_dying << 8) | unp->unp_stopping, status); 464 (usbnet_isdying(un) << 8) | unp->unp_stopping, status);
465 return; 465 return;
466 } 466 }
467 467
468 if (status != USBD_NORMAL_COMPLETION) { 468 if (status != USBD_NORMAL_COMPLETION) {
469 if (usbd_ratecheck(&unp->unp_intr_notice)) { 469 if (usbd_ratecheck(&unp->unp_intr_notice)) {
470 aprint_error_dev(un->un_dev, "usb error on intr: %s\n", 470 aprint_error_dev(un->un_dev, "usb error on intr: %s\n",
471 usbd_errstr(status)); 471 usbd_errstr(status));
472 } 472 }
473 if (status == USBD_STALLED) 473 if (status == USBD_STALLED)
474 usbd_clear_endpoint_stall_async(unp->unp_ep[USBNET_ENDPT_INTR]); 474 usbd_clear_endpoint_stall_async(unp->unp_ep[USBNET_ENDPT_INTR]);
475 USBNETHIST_CALLARGS("%jd: not normal status %#jx", 475 USBNETHIST_CALLARGS("%jd: not normal status %#jx",
476 unp->unp_number, status, 0, 0); 476 unp->unp_number, status, 0, 0);
477 return; 477 return;
@@ -827,27 +827,27 @@ int @@ -827,27 +827,27 @@ int
827usbnet_init_rx_tx(struct usbnet * const un) 827usbnet_init_rx_tx(struct usbnet * const un)
828{ 828{
829 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 829 USBNETHIST_FUNC(); USBNETHIST_CALLED();
830 struct usbnet_private * const unp = un->un_pri; 830 struct usbnet_private * const unp = un->un_pri;
831 struct ifnet * const ifp = usbnet_ifp(un); 831 struct ifnet * const ifp = usbnet_ifp(un);
832 usbd_status err; 832 usbd_status err;
833 int error = 0; 833 int error = 0;
834 834
835 KASSERTMSG(!unp->unp_ifp_attached || IFNET_LOCKED(ifp), 835 KASSERTMSG(!unp->unp_ifp_attached || IFNET_LOCKED(ifp),
836 "%s", ifp->if_xname); 836 "%s", ifp->if_xname);
837 837
838 usbnet_isowned_core(un); 838 usbnet_isowned_core(un);
839 839
840 if (unp->unp_dying) { 840 if (usbnet_isdying(un)) {
841 return EIO; 841 return EIO;
842 } 842 }
843 843
844 usbnet_busy(un); 844 usbnet_busy(un);
845 845
846 /* Open RX and TX pipes. */ 846 /* Open RX and TX pipes. */
847 err = usbnet_ep_open_pipes(un); 847 err = usbnet_ep_open_pipes(un);
848 if (err) { 848 if (err) {
849 aprint_error_dev(un->un_dev, "open rx/tx pipes failed: %s\n", 849 aprint_error_dev(un->un_dev, "open rx/tx pipes failed: %s\n",
850 usbd_errstr(err)); 850 usbd_errstr(err));
851 error = EIO; 851 error = EIO;
852 goto out; 852 goto out;
853 } 853 }
@@ -908,71 +908,69 @@ usbnet_unbusy(struct usbnet *un) @@ -908,71 +908,69 @@ usbnet_unbusy(struct usbnet *un)
908 usbnet_isowned_core(un); 908 usbnet_isowned_core(un);
909 909
910 if (--unp->unp_refcnt < 0) 910 if (--unp->unp_refcnt < 0)
911 cv_broadcast(&unp->unp_detachcv); 911 cv_broadcast(&unp->unp_detachcv);
912} 912}
913 913
914/* MII management. */ 914/* MII management. */
915 915
916int 916int
917usbnet_mii_readreg(device_t dev, int phy, int reg, uint16_t *val) 917usbnet_mii_readreg(device_t dev, int phy, int reg, uint16_t *val)
918{ 918{
919 USBNETHIST_FUNC(); 919 USBNETHIST_FUNC();
920 struct usbnet * const un = device_private(dev); 920 struct usbnet * const un = device_private(dev);
921 struct usbnet_private * const unp = un->un_pri; 
922 int err; 921 int err;
923 922
924 /* MII layer ensures core_lock is held. */ 923 /* MII layer ensures core_lock is held. */
925 usbnet_isowned_core(un); 924 usbnet_isowned_core(un);
926 925
927 if (unp->unp_dying) { 926 if (usbnet_isdying(un)) {
928 return EIO; 927 return EIO;
929 } 928 }
930 929
931 usbnet_busy(un); 930 usbnet_busy(un);
932 err = uno_read_reg(un, phy, reg, val); 931 err = uno_read_reg(un, phy, reg, val);
933 usbnet_unbusy(un); 932 usbnet_unbusy(un);
934 933
935 if (err) { 934 if (err) {
936 USBNETHIST_CALLARGS("%jd: read PHY failed: %jd", 935 USBNETHIST_CALLARGS("%jd: read PHY failed: %jd",
937 unp->unp_number, err, 0, 0); 936 un->un_pri->unp_number, err, 0, 0);
938 return err; 937 return err;
939 } 938 }
940 939
941 return 0; 940 return 0;
942} 941}
943 942
944int 943int
945usbnet_mii_writereg(device_t dev, int phy, int reg, uint16_t val) 944usbnet_mii_writereg(device_t dev, int phy, int reg, uint16_t val)
946{ 945{
947 USBNETHIST_FUNC(); 946 USBNETHIST_FUNC();
948 struct usbnet * const un = device_private(dev); 947 struct usbnet * const un = device_private(dev);
949 struct usbnet_private * const unp = un->un_pri; 
950 int err; 948 int err;
951 949
952 /* MII layer ensures core_lock is held. */ 950 /* MII layer ensures core_lock is held. */
953 usbnet_isowned_core(un); 951 usbnet_isowned_core(un);
954 952
955 if (unp->unp_dying) { 953 if (usbnet_isdying(un)) {
956 return EIO; 954 return EIO;
957 } 955 }
958 956
959 usbnet_busy(un); 957 usbnet_busy(un);
960 err = uno_write_reg(un, phy, reg, val); 958 err = uno_write_reg(un, phy, reg, val);
961 usbnet_unbusy(un); 959 usbnet_unbusy(un);
962 960
963 if (err) { 961 if (err) {
964 USBNETHIST_CALLARGS("%jd: write PHY failed: %jd", 962 USBNETHIST_CALLARGS("%jd: write PHY failed: %jd",
965 unp->unp_number, err, 0, 0); 963 un->un_pri->unp_number, err, 0, 0);
966 return err; 964 return err;
967 } 965 }
968 966
969 return 0; 967 return 0;
970} 968}
971 969
972void 970void
973usbnet_mii_statchg(struct ifnet *ifp) 971usbnet_mii_statchg(struct ifnet *ifp)
974{ 972{
975 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 973 USBNETHIST_FUNC(); USBNETHIST_CALLED();
976 struct usbnet * const un = ifp->if_softc; 974 struct usbnet * const un = ifp->if_softc;
977 975
978 /* MII layer ensures core_lock is held. */ 976 /* MII layer ensures core_lock is held. */
@@ -987,27 +985,27 @@ static int @@ -987,27 +985,27 @@ static int
987usbnet_media_upd(struct ifnet *ifp) 985usbnet_media_upd(struct ifnet *ifp)
988{ 986{
989 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 987 USBNETHIST_FUNC(); USBNETHIST_CALLED();
990 struct usbnet * const un = ifp->if_softc; 988 struct usbnet * const un = ifp->if_softc;
991 struct usbnet_private * const unp = un->un_pri; 989 struct usbnet_private * const unp = un->un_pri;
992 struct mii_data * const mii = usbnet_mii(un); 990 struct mii_data * const mii = usbnet_mii(un);
993 991
994 /* ifmedia layer ensures core_lock is held. */ 992 /* ifmedia layer ensures core_lock is held. */
995 usbnet_isowned_core(un); 993 usbnet_isowned_core(un);
996 994
997 /* ifmedia changes only with IFNET_LOCK held. */ 995 /* ifmedia changes only with IFNET_LOCK held. */
998 KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 996 KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname);
999 997
1000 if (unp->unp_dying) 998 if (usbnet_isdying(un))
1001 return EIO; 999 return EIO;
1002 1000
1003 unp->unp_link = false; 1001 unp->unp_link = false;
1004 1002
1005 if (mii->mii_instance) { 1003 if (mii->mii_instance) {
1006 struct mii_softc *miisc; 1004 struct mii_softc *miisc;
1007 1005
1008 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 1006 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
1009 mii_phy_reset(miisc); 1007 mii_phy_reset(miisc);
1010 } 1008 }
1011 1009
1012 return ether_mediachange(ifp); 1010 return ether_mediachange(ifp);
1013} 1011}
@@ -1075,36 +1073,36 @@ usbnet_if_ioctl(struct ifnet *ifp, u_lon @@ -1075,36 +1073,36 @@ usbnet_if_ioctl(struct ifnet *ifp, u_lon
1075static void 1073static void
1076usbnet_mcast_task(void *arg) 1074usbnet_mcast_task(void *arg)
1077{ 1075{
1078 USBNETHIST_FUNC(); 1076 USBNETHIST_FUNC();
1079 struct usbnet * const un = arg; 1077 struct usbnet * const un = arg;
1080 struct usbnet_private * const unp = un->un_pri; 1078 struct usbnet_private * const unp = un->un_pri;
1081 struct ifnet * const ifp = usbnet_ifp(un); 1079 struct ifnet * const ifp = usbnet_ifp(un);
1082 bool dying; 1080 bool dying;
1083 struct ifreq ifr; 1081 struct ifreq ifr;
1084 1082
1085 USBNETHIST_CALLARGSN(10, "%jd: enter", unp->unp_number, 0, 0, 0); 1083 USBNETHIST_CALLARGSN(10, "%jd: enter", unp->unp_number, 0, 0, 0);
1086 1084
1087 /* 1085 /*
1088 * If we're detaching, we must check unp_dying _before_ 1086 * If we're detaching, we must check usbnet_isdying _before_
1089 * touching IFNET_LOCK -- the ifnet may have been detached by 1087 * touching IFNET_LOCK -- the ifnet may have been detached by
1090 * the time this task runs. This is racy -- unp_dying may be 1088 * the time this task runs. This is racy -- unp_dying may be
1091 * set immediately after we test it -- but nevertheless safe, 1089 * set immediately after we test it -- but nevertheless safe,
1092 * because usbnet_detach waits for the task to complete before 1090 * because usbnet_detach waits for the task to complete before
1093 * issuing if_detach, and necessary, so that we don't touch 1091 * issuing if_detach, and necessary, so that we don't touch
1094 * IFNET_LOCK after if_detach. See usbnet_detach for details. 1092 * IFNET_LOCK after if_detach. See usbnet_detach for details.
1095 */ 1093 */
1096 mutex_enter(&unp->unp_core_lock); 1094 mutex_enter(&unp->unp_core_lock);
1097 dying = unp->unp_dying; 1095 dying = usbnet_isdying(un);
1098 mutex_exit(&unp->unp_core_lock); 1096 mutex_exit(&unp->unp_core_lock);
1099 if (dying) 1097 if (dying)
1100 return; 1098 return;
1101 1099
1102 /* 1100 /*
1103 * Pass a bogus ifr with SIOCDELMULTI -- the goal is to just 1101 * Pass a bogus ifr with SIOCDELMULTI -- the goal is to just
1104 * notify the driver to reprogram any hardware multicast 1102 * notify the driver to reprogram any hardware multicast
1105 * filter, according to what's already stored in the ethercom. 1103 * filter, according to what's already stored in the ethercom.
1106 * None of the drivers actually examine this argument, so it 1104 * None of the drivers actually examine this argument, so it
1107 * doesn't change the ABI as far as they can tell. 1105 * doesn't change the ABI as far as they can tell.
1108 */ 1106 */
1109 IFNET_LOCK(ifp); 1107 IFNET_LOCK(ifp);
1110 if (ifp->if_flags & IFF_RUNNING) { 1108 if (ifp->if_flags & IFF_RUNNING) {
@@ -1161,27 +1159,27 @@ usbnet_stop(struct usbnet *un, struct if @@ -1161,27 +1159,27 @@ usbnet_stop(struct usbnet *un, struct if
1161 usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER, 1159 usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER,
1162 &unp->unp_core_lock); 1160 &unp->unp_core_lock);
1163 1161
1164 /* 1162 /*
1165 * Now that the software is quiescent, ask the driver to stop 1163 * Now that the software is quiescent, ask the driver to stop
1166 * the hardware. The driver's uno_stop routine now has 1164 * the hardware. The driver's uno_stop routine now has
1167 * exclusive access to any registers that might previously have 1165 * exclusive access to any registers that might previously have
1168 * been used by to ifmedia, mii, or ioctl callbacks. 1166 * been used by to ifmedia, mii, or ioctl callbacks.
1169 * 1167 *
1170 * Don't bother if the device is being detached, though -- if 1168 * Don't bother if the device is being detached, though -- if
1171 * it's been unplugged then there's no point in trying to touch 1169 * it's been unplugged then there's no point in trying to touch
1172 * the registers. 1170 * the registers.
1173 */ 1171 */
1174 if (!unp->unp_dying) 1172 if (!usbnet_isdying(un))
1175 uno_stop(un, ifp, disable); 1173 uno_stop(un, ifp, disable);
1176 1174
1177 /* Stop transfers. */ 1175 /* Stop transfers. */
1178 usbnet_ep_stop_pipes(un); 1176 usbnet_ep_stop_pipes(un);
1179 1177
1180 /* Free RX/TX resources. */ 1178 /* Free RX/TX resources. */
1181 usbnet_rx_list_fini(un); 1179 usbnet_rx_list_fini(un);
1182 usbnet_tx_list_fini(un); 1180 usbnet_tx_list_fini(un);
1183 1181
1184 /* Close pipes. */ 1182 /* Close pipes. */
1185 usbnet_ep_close_pipes(un); 1183 usbnet_ep_close_pipes(un);
1186 1184
1187 /* Everything is quesced now. */ 1185 /* Everything is quesced now. */
@@ -1270,47 +1268,47 @@ usbnet_tick_task(void *arg) @@ -1270,47 +1268,47 @@ usbnet_tick_task(void *arg)
1270 DPRINTFN(8, "mii %#jx ifp %#jx", (uintptr_t)mii, (uintptr_t)ifp, 0, 0); 1268 DPRINTFN(8, "mii %#jx ifp %#jx", (uintptr_t)mii, (uintptr_t)ifp, 0, 0);
1271 if (mii) { 1269 if (mii) {
1272 mutex_enter(&unp->unp_core_lock); 1270 mutex_enter(&unp->unp_core_lock);
1273 mii_tick(mii); 1271 mii_tick(mii);
1274 if (!unp->unp_link) 1272 if (!unp->unp_link)
1275 (*mii->mii_statchg)(ifp); 1273 (*mii->mii_statchg)(ifp);
1276 mutex_exit(&unp->unp_core_lock); 1274 mutex_exit(&unp->unp_core_lock);
1277 } 1275 }
1278 1276
1279 /* Call driver if requested. */ 1277 /* Call driver if requested. */
1280 uno_tick(un); 1278 uno_tick(un);
1281 1279
1282 mutex_enter(&unp->unp_core_lock); 1280 mutex_enter(&unp->unp_core_lock);
1283 if (!unp->unp_stopping && !unp->unp_dying) 1281 if (!unp->unp_stopping && !usbnet_isdying(un))
1284 callout_schedule(&unp->unp_stat_ch, hz); 1282 callout_schedule(&unp->unp_stat_ch, hz);
1285 mutex_exit(&unp->unp_core_lock); 1283 mutex_exit(&unp->unp_core_lock);
1286} 1284}
1287 1285
1288static int 1286static int
1289usbnet_if_init(struct ifnet *ifp) 1287usbnet_if_init(struct ifnet *ifp)
1290{ 1288{
1291 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 1289 USBNETHIST_FUNC(); USBNETHIST_CALLED();
1292 struct usbnet * const un = ifp->if_softc; 1290 struct usbnet * const un = ifp->if_softc;
1293 bool dying; 1291 bool dying;
1294 int error; 1292 int error;
1295 1293
1296 KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 1294 KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname);
1297 1295
1298 /* 1296 /*
1299 * Prevent anyone from bringing the interface back up once 1297 * Prevent anyone from bringing the interface back up once
1300 * we're detaching. 1298 * we're detaching.
1301 */ 1299 */
1302 mutex_enter(&un->un_pri->unp_core_lock); 1300 mutex_enter(&un->un_pri->unp_core_lock);
1303 dying = un->un_pri->unp_dying; 1301 dying = usbnet_isdying(un);
1304 mutex_exit(&un->un_pri->unp_core_lock); 1302 mutex_exit(&un->un_pri->unp_core_lock);
1305 if (dying) 1303 if (dying)
1306 return EIO; 1304 return EIO;
1307 1305
1308 mutex_enter(&un->un_pri->unp_core_lock); 1306 mutex_enter(&un->un_pri->unp_core_lock);
1309 error = uno_init(un, ifp); 1307 error = uno_init(un, ifp);
1310 mutex_exit(&un->un_pri->unp_core_lock); 1308 mutex_exit(&un->un_pri->unp_core_lock);
1311 1309
1312 return error; 1310 return error;
1313} 1311}
1314 1312
1315 1313
1316/* Various accessors. */ 1314/* Various accessors. */
@@ -1350,27 +1348,27 @@ usbnet_softc(struct usbnet *un) @@ -1350,27 +1348,27 @@ usbnet_softc(struct usbnet *un)
1350{ 1348{
1351 return un->un_sc; 1349 return un->un_sc;
1352} 1350}
1353 1351
1354bool 1352bool
1355usbnet_havelink(struct usbnet *un) 1353usbnet_havelink(struct usbnet *un)
1356{ 1354{
1357 return un->un_pri->unp_link; 1355 return un->un_pri->unp_link;
1358} 1356}
1359 1357
1360bool 1358bool
1361usbnet_isdying(struct usbnet *un) 1359usbnet_isdying(struct usbnet *un)
1362{ 1360{
1363 return un->un_pri->unp_dying; 1361 return atomic_load_relaxed(&un->un_pri->unp_dying);
1364} 1362}
1365 1363
1366 1364
1367/* Locking. */ 1365/* Locking. */
1368 1366
1369void 1367void
1370usbnet_lock_core(struct usbnet *un) 1368usbnet_lock_core(struct usbnet *un)
1371{ 1369{
1372 mutex_enter(&un->un_pri->unp_core_lock); 1370 mutex_enter(&un->un_pri->unp_core_lock);
1373} 1371}
1374 1372
1375void 1373void
1376usbnet_unlock_core(struct usbnet *un) 1374usbnet_unlock_core(struct usbnet *un)
@@ -1584,27 +1582,27 @@ usbnet_detach(device_t self, int flags) @@ -1584,27 +1582,27 @@ usbnet_detach(device_t self, int flags)
1584 1582
1585 /* Detached before attached finished, so just bail out. */ 1583 /* Detached before attached finished, so just bail out. */
1586 if (unp == NULL || !unp->unp_attached) 1584 if (unp == NULL || !unp->unp_attached)
1587 return 0; 1585 return 0;
1588 1586
1589 struct ifnet * const ifp = usbnet_ifp(un); 1587 struct ifnet * const ifp = usbnet_ifp(un);
1590 struct mii_data * const mii = usbnet_mii(un); 1588 struct mii_data * const mii = usbnet_mii(un);
1591 1589
1592 /* 1590 /*
1593 * Prevent new activity. After we stop the interface, it 1591 * Prevent new activity. After we stop the interface, it
1594 * cannot be brought back up. 1592 * cannot be brought back up.
1595 */ 1593 */
1596 mutex_enter(&unp->unp_core_lock); 1594 mutex_enter(&unp->unp_core_lock);
1597 unp->unp_dying = true; 1595 atomic_store_relaxed(&unp->unp_dying, true);
1598 mutex_exit(&unp->unp_core_lock); 1596 mutex_exit(&unp->unp_core_lock);
1599 1597
1600 /* 1598 /*
1601 * If we're still running on the network, stop and wait for all 1599 * If we're still running on the network, stop and wait for all
1602 * asynchronous activity to finish. 1600 * asynchronous activity to finish.
1603 * 1601 *
1604 * If usbnet_attach_ifp never ran, IFNET_LOCK won't work, but 1602 * If usbnet_attach_ifp never ran, IFNET_LOCK won't work, but
1605 * no activity is possible, so just skip this part. 1603 * no activity is possible, so just skip this part.
1606 */ 1604 */
1607 if (unp->unp_ifp_attached) { 1605 if (unp->unp_ifp_attached) {
1608 IFNET_LOCK(ifp); 1606 IFNET_LOCK(ifp);
1609 if (ifp->if_flags & IFF_RUNNING) { 1607 if (ifp->if_flags & IFF_RUNNING) {
1610 usbnet_if_stop(ifp, 1); 1608 usbnet_if_stop(ifp, 1);
@@ -1713,27 +1711,27 @@ usbnet_detach(device_t self, int flags) @@ -1713,27 +1711,27 @@ usbnet_detach(device_t self, int flags)
1713int 1711int
1714usbnet_activate(device_t self, devact_t act) 1712usbnet_activate(device_t self, devact_t act)
1715{ 1713{
1716 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 1714 USBNETHIST_FUNC(); USBNETHIST_CALLED();
1717 struct usbnet * const un = device_private(self); 1715 struct usbnet * const un = device_private(self);
1718 struct usbnet_private * const unp = un->un_pri; 1716 struct usbnet_private * const unp = un->un_pri;
1719 struct ifnet * const ifp = usbnet_ifp(un); 1717 struct ifnet * const ifp = usbnet_ifp(un);
1720 1718
1721 switch (act) { 1719 switch (act) {
1722 case DVACT_DEACTIVATE: 1720 case DVACT_DEACTIVATE:
1723 if_deactivate(ifp); 1721 if_deactivate(ifp);
1724 1722
1725 mutex_enter(&unp->unp_core_lock); 1723 mutex_enter(&unp->unp_core_lock);
1726 unp->unp_dying = true; 1724 atomic_store_relaxed(&unp->unp_dying, true);
1727 mutex_exit(&unp->unp_core_lock); 1725 mutex_exit(&unp->unp_core_lock);
1728 1726
1729 mutex_enter(&unp->unp_rxlock); 1727 mutex_enter(&unp->unp_rxlock);
1730 mutex_enter(&unp->unp_txlock); 1728 mutex_enter(&unp->unp_txlock);
1731 unp->unp_stopping = true; 1729 unp->unp_stopping = true;
1732 mutex_exit(&unp->unp_txlock); 1730 mutex_exit(&unp->unp_txlock);
1733 mutex_exit(&unp->unp_rxlock); 1731 mutex_exit(&unp->unp_rxlock);
1734 1732
1735 return 0; 1733 return 0;
1736 default: 1734 default:
1737 return EOPNOTSUPP; 1735 return EOPNOTSUPP;
1738 } 1736 }
1739} 1737}