| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: usbnet.c,v 1.73 2022/03/03 05:50:39 riastradh Exp $ */ | | 1 | /* $NetBSD: usbnet.c,v 1.74 2022/03/03 05:50:47 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.73 2022/03/03 05:50:39 riastradh Exp $"); | | 34 | __KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.74 2022/03/03 05:50:47 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 | |
45 | struct usbnet_cdata { | | 45 | struct 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; |
| @@ -1065,46 +1065,42 @@ usbnet_if_ioctl(struct ifnet *ifp, u_lon | | | @@ -1065,46 +1065,42 @@ usbnet_if_ioctl(struct ifnet *ifp, u_lon |
1065 | default: | | 1065 | default: |
1066 | error = uno_ioctl(un, ifp, cmd, data); | | 1066 | error = uno_ioctl(un, ifp, cmd, data); |
1067 | } | | 1067 | } |
1068 | } | | 1068 | } |
1069 | | | 1069 | |
1070 | return error; | | 1070 | return error; |
1071 | } | | 1071 | } |
1072 | | | 1072 | |
1073 | static void | | 1073 | static void |
1074 | usbnet_mcast_task(void *arg) | | 1074 | usbnet_mcast_task(void *arg) |
1075 | { | | 1075 | { |
1076 | USBNETHIST_FUNC(); | | 1076 | USBNETHIST_FUNC(); |
1077 | struct usbnet * const un = arg; | | 1077 | struct usbnet * const un = arg; |
1078 | struct usbnet_private * const unp = un->un_pri; | | | |
1079 | struct ifnet * const ifp = usbnet_ifp(un); | | 1078 | struct ifnet * const ifp = usbnet_ifp(un); |
1080 | bool dying; | | | |
1081 | struct ifreq ifr; | | 1079 | struct ifreq ifr; |
1082 | | | 1080 | |
1083 | USBNETHIST_CALLARGSN(10, "%jd: enter", unp->unp_number, 0, 0, 0); | | 1081 | USBNETHIST_CALLARGSN(10, "%jd: enter", |
| | | 1082 | un->un_pri->unp_number, 0, 0, 0); |
1084 | | | 1083 | |
1085 | /* | | 1084 | /* |
1086 | * If we're detaching, we must check usbnet_isdying _before_ | | 1085 | * If we're detaching, we must check usbnet_isdying _before_ |
1087 | * touching IFNET_LOCK -- the ifnet may have been detached by | | 1086 | * touching IFNET_LOCK -- the ifnet may have been detached by |
1088 | * the time this task runs. This is racy -- unp_dying may be | | 1087 | * the time this task runs. This is racy -- unp_dying may be |
1089 | * set immediately after we test it -- but nevertheless safe, | | 1088 | * set immediately after we test it -- but nevertheless safe, |
1090 | * because usbnet_detach waits for the task to complete before | | 1089 | * because usbnet_detach waits for the task to complete before |
1091 | * issuing if_detach, and necessary, so that we don't touch | | 1090 | * issuing if_detach, and necessary, so that we don't touch |
1092 | * IFNET_LOCK after if_detach. See usbnet_detach for details. | | 1091 | * IFNET_LOCK after if_detach. See usbnet_detach for details. |
1093 | */ | | 1092 | */ |
1094 | mutex_enter(&unp->unp_core_lock); | | 1093 | if (usbnet_isdying(un)) |
1095 | dying = usbnet_isdying(un); | | | |
1096 | mutex_exit(&unp->unp_core_lock); | | | |
1097 | if (dying) | | | |
1098 | return; | | 1094 | return; |
1099 | | | 1095 | |
1100 | /* | | 1096 | /* |
1101 | * Pass a bogus ifr with SIOCDELMULTI -- the goal is to just | | 1097 | * Pass a bogus ifr with SIOCDELMULTI -- the goal is to just |
1102 | * notify the driver to reprogram any hardware multicast | | 1098 | * notify the driver to reprogram any hardware multicast |
1103 | * filter, according to what's already stored in the ethercom. | | 1099 | * filter, according to what's already stored in the ethercom. |
1104 | * None of the drivers actually examine this argument, so it | | 1100 | * None of the drivers actually examine this argument, so it |
1105 | * doesn't change the ABI as far as they can tell. | | 1101 | * doesn't change the ABI as far as they can tell. |
1106 | */ | | 1102 | */ |
1107 | IFNET_LOCK(ifp); | | 1103 | IFNET_LOCK(ifp); |
1108 | if (ifp->if_flags & IFF_RUNNING) { | | 1104 | if (ifp->if_flags & IFF_RUNNING) { |
1109 | memset(&ifr, 0, sizeof(ifr)); | | 1105 | memset(&ifr, 0, sizeof(ifr)); |
1110 | (void)uno_ioctl(un, ifp, SIOCDELMULTI, &ifr); | | 1106 | (void)uno_ioctl(un, ifp, SIOCDELMULTI, &ifr); |
| @@ -1278,39 +1274,35 @@ usbnet_tick_task(void *arg) | | | @@ -1278,39 +1274,35 @@ usbnet_tick_task(void *arg) |
1278 | uno_tick(un); | | 1274 | uno_tick(un); |
1279 | | | 1275 | |
1280 | mutex_enter(&unp->unp_core_lock); | | 1276 | mutex_enter(&unp->unp_core_lock); |
1281 | if (!unp->unp_stopping && !usbnet_isdying(un)) | | 1277 | if (!unp->unp_stopping && !usbnet_isdying(un)) |
1282 | callout_schedule(&unp->unp_stat_ch, hz); | | 1278 | callout_schedule(&unp->unp_stat_ch, hz); |
1283 | mutex_exit(&unp->unp_core_lock); | | 1279 | mutex_exit(&unp->unp_core_lock); |
1284 | } | | 1280 | } |
1285 | | | 1281 | |
1286 | static int | | 1282 | static int |
1287 | usbnet_if_init(struct ifnet *ifp) | | 1283 | usbnet_if_init(struct ifnet *ifp) |
1288 | { | | 1284 | { |
1289 | USBNETHIST_FUNC(); USBNETHIST_CALLED(); | | 1285 | USBNETHIST_FUNC(); USBNETHIST_CALLED(); |
1290 | struct usbnet * const un = ifp->if_softc; | | 1286 | struct usbnet * const un = ifp->if_softc; |
1291 | bool dying; | | | |
1292 | int error; | | 1287 | int error; |
1293 | | | 1288 | |
1294 | KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); | | 1289 | KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); |
1295 | | | 1290 | |
1296 | /* | | 1291 | /* |
1297 | * Prevent anyone from bringing the interface back up once | | 1292 | * Prevent anyone from bringing the interface back up once |
1298 | * we're detaching. | | 1293 | * we're detaching. |
1299 | */ | | 1294 | */ |
1300 | mutex_enter(&un->un_pri->unp_core_lock); | | 1295 | if (usbnet_isdying(un)) |
1301 | dying = usbnet_isdying(un); | | | |
1302 | mutex_exit(&un->un_pri->unp_core_lock); | | | |
1303 | if (dying) | | | |
1304 | return EIO; | | 1296 | return EIO; |
1305 | | | 1297 | |
1306 | mutex_enter(&un->un_pri->unp_core_lock); | | 1298 | mutex_enter(&un->un_pri->unp_core_lock); |
1307 | error = uno_init(un, ifp); | | 1299 | error = uno_init(un, ifp); |
1308 | mutex_exit(&un->un_pri->unp_core_lock); | | 1300 | mutex_exit(&un->un_pri->unp_core_lock); |
1309 | | | 1301 | |
1310 | return error; | | 1302 | return error; |
1311 | } | | 1303 | } |
1312 | | | 1304 | |
1313 | | | 1305 | |
1314 | /* Various accessors. */ | | 1306 | /* Various accessors. */ |
1315 | | | 1307 | |
1316 | void | | 1308 | void |
| @@ -1581,29 +1573,27 @@ usbnet_detach(device_t self, int flags) | | | @@ -1581,29 +1573,27 @@ usbnet_detach(device_t self, int flags) |
1581 | struct usbnet_private * const unp = un->un_pri; | | 1573 | struct usbnet_private * const unp = un->un_pri; |
1582 | | | 1574 | |
1583 | /* Detached before attached finished, so just bail out. */ | | 1575 | /* Detached before attached finished, so just bail out. */ |
1584 | if (unp == NULL || !unp->unp_attached) | | 1576 | if (unp == NULL || !unp->unp_attached) |
1585 | return 0; | | 1577 | return 0; |
1586 | | | 1578 | |
1587 | struct ifnet * const ifp = usbnet_ifp(un); | | 1579 | struct ifnet * const ifp = usbnet_ifp(un); |
1588 | struct mii_data * const mii = usbnet_mii(un); | | 1580 | struct mii_data * const mii = usbnet_mii(un); |
1589 | | | 1581 | |
1590 | /* | | 1582 | /* |
1591 | * Prevent new activity. After we stop the interface, it | | 1583 | * Prevent new activity. After we stop the interface, it |
1592 | * cannot be brought back up. | | 1584 | * cannot be brought back up. |
1593 | */ | | 1585 | */ |
1594 | mutex_enter(&unp->unp_core_lock); | | | |
1595 | atomic_store_relaxed(&unp->unp_dying, true); | | 1586 | atomic_store_relaxed(&unp->unp_dying, true); |
1596 | mutex_exit(&unp->unp_core_lock); | | | |
1597 | | | 1587 | |
1598 | /* | | 1588 | /* |
1599 | * If we're still running on the network, stop and wait for all | | 1589 | * If we're still running on the network, stop and wait for all |
1600 | * asynchronous activity to finish. | | 1590 | * asynchronous activity to finish. |
1601 | * | | 1591 | * |
1602 | * If usbnet_attach_ifp never ran, IFNET_LOCK won't work, but | | 1592 | * If usbnet_attach_ifp never ran, IFNET_LOCK won't work, but |
1603 | * no activity is possible, so just skip this part. | | 1593 | * no activity is possible, so just skip this part. |
1604 | */ | | 1594 | */ |
1605 | if (unp->unp_ifp_attached) { | | 1595 | if (unp->unp_ifp_attached) { |
1606 | IFNET_LOCK(ifp); | | 1596 | IFNET_LOCK(ifp); |
1607 | if (ifp->if_flags & IFF_RUNNING) { | | 1597 | if (ifp->if_flags & IFF_RUNNING) { |
1608 | usbnet_if_stop(ifp, 1); | | 1598 | usbnet_if_stop(ifp, 1); |
1609 | } | | 1599 | } |
| @@ -1710,29 +1700,27 @@ usbnet_detach(device_t self, int flags) | | | @@ -1710,29 +1700,27 @@ usbnet_detach(device_t self, int flags) |
1710 | | | 1700 | |
1711 | int | | 1701 | int |
1712 | usbnet_activate(device_t self, devact_t act) | | 1702 | usbnet_activate(device_t self, devact_t act) |
1713 | { | | 1703 | { |
1714 | USBNETHIST_FUNC(); USBNETHIST_CALLED(); | | 1704 | USBNETHIST_FUNC(); USBNETHIST_CALLED(); |
1715 | struct usbnet * const un = device_private(self); | | 1705 | struct usbnet * const un = device_private(self); |
1716 | struct usbnet_private * const unp = un->un_pri; | | 1706 | struct usbnet_private * const unp = un->un_pri; |
1717 | struct ifnet * const ifp = usbnet_ifp(un); | | 1707 | struct ifnet * const ifp = usbnet_ifp(un); |
1718 | | | 1708 | |
1719 | switch (act) { | | 1709 | switch (act) { |
1720 | case DVACT_DEACTIVATE: | | 1710 | case DVACT_DEACTIVATE: |
1721 | if_deactivate(ifp); | | 1711 | if_deactivate(ifp); |
1722 | | | 1712 | |
1723 | mutex_enter(&unp->unp_core_lock); | | | |
1724 | atomic_store_relaxed(&unp->unp_dying, true); | | 1713 | atomic_store_relaxed(&unp->unp_dying, true); |
1725 | mutex_exit(&unp->unp_core_lock); | | | |
1726 | | | 1714 | |
1727 | mutex_enter(&unp->unp_rxlock); | | 1715 | mutex_enter(&unp->unp_rxlock); |
1728 | mutex_enter(&unp->unp_txlock); | | 1716 | mutex_enter(&unp->unp_txlock); |
1729 | unp->unp_stopping = true; | | 1717 | unp->unp_stopping = true; |
1730 | mutex_exit(&unp->unp_txlock); | | 1718 | mutex_exit(&unp->unp_txlock); |
1731 | mutex_exit(&unp->unp_rxlock); | | 1719 | mutex_exit(&unp->unp_rxlock); |
1732 | | | 1720 | |
1733 | return 0; | | 1721 | return 0; |
1734 | default: | | 1722 | default: |
1735 | return EOPNOTSUPP; | | 1723 | return EOPNOTSUPP; |
1736 | } | | 1724 | } |
1737 | } | | 1725 | } |
1738 | | | 1726 | |