From 6573cec411727c3bafec2e807b23b8d188f3faf0 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 26 Dec 2021 00:21:10 +0000 Subject: [PATCH 01/77] usbnet: Defer hardware multicast filter updates to USB task. Breaks deadlock: - usbnet_detach holds usbnet lock, awaits kpause in ure_reset - callout holds softclock `lock' (sequential softints, blocks kpause wakeup), awaits softnet_lock in tcp_timer_keep, frag6_fasttimo, &c. - soclose holds softnet_lock, awaits usbnet lock in SIOCDELMULTI This change breaks the deadlock by not passing the SIOCADDMULTI or SIOCDELMULTI ioctl synchronously to the driver, which typically takes the usbnet lock. With this change, the ethernet layer still maintains the list of multicast addresses synchronously, but we defer the driver logic that updates the hardware multicast filter to an asynchronous USB task without softnet_lock held. This doesn't cause exactly the same ioctl to be sent to the driver -- usbnet just sends SIOCDELMULTI with an all-zero struct ifreq, and might drop some ioctls if issued in quick succession. This is OK because none of the drivers actually distinguish between SIOCADDMULTI and SIOCDELMULTI, or examine the argument; the drivers just commit whatever multicast addresses are listed in the ethercom. --- sys/dev/usb/usbnet.c | 98 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 95 insertions(+), 3 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 1712d2f687f0..9fa061b3cea0 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -72,6 +72,7 @@ struct usbnet_private { struct ethercom unp_ec; struct mii_data unp_mii; + struct usb_task unp_mcasttask; struct usb_task unp_ticktask; struct callout unp_stat_ch; struct usbd_pipe *unp_ep[USBNET_ENDPT_MAX]; @@ -1035,12 +1036,64 @@ usbnet_if_ioctl(struct ifnet *ifp, u_long cmd, void *data) return uno_override_ioctl(un, ifp, cmd, data); error = ether_ioctl(ifp, cmd, data); - if (error == ENETRESET) - error = uno_ioctl(un, ifp, cmd, data); + if (error == ENETRESET) { + switch (cmd) { + case SIOCADDMULTI: + case SIOCDELMULTI: + usb_add_task(un->un_udev, &unp->unp_mcasttask, + USB_TASKQ_DRIVER); + error = 0; + break; + default: + error = uno_ioctl(un, ifp, cmd, data); + } + } return error; } +static void +usbnet_mcast_task(void *arg) +{ + USBNETHIST_FUNC(); + struct usbnet * const un = arg; + struct usbnet_private * const unp = un->un_pri; + struct ifnet * const ifp = usbnet_ifp(un); + bool dying; + struct ifreq ifr; + + USBNETHIST_CALLARGSN(10, "%jd: enter", unp->unp_number, 0, 0, 0); + + /* + * If we're detaching, we must check unp_dying _before_ + * touching IFNET_LOCK -- the ifnet may have been detached by + * the time this task runs. This is racy -- unp_dying may be + * set immediately after we test it -- but nevertheless safe, + * because usbnet_detach waits for the task to complete before + * issuing if_detach, and necessary, so that we don't touch + * IFNET_LOCK after if_detach. See usbnet_detach for details. + */ + mutex_enter(&unp->unp_core_lock); + dying = unp->unp_dying; + mutex_exit(&unp->unp_core_lock); + if (dying) + return; + + /* + * Pass a bogus ifr with SIOCDELMULTI -- the goal is to just + * notify the driver to reprogram any hardware multicast + * filter, according to what's already stored in the ethercom. + * None of the drivers actually examine this argument, so it + * doesn't change the ABI as far as they can tell. + */ + IFNET_LOCK(ifp); + if (ifp->if_flags & IFF_RUNNING) { + memset(&ifr, 0, sizeof(ifr)); + (void)uno_ioctl(un, ifp, SIOCDELMULTI, &ifr); + } + IFNET_UNLOCK(ifp); +} + /* * Generic stop network function: * - mark as stopping @@ -1373,7 +1426,10 @@ usbnet_attach(struct usbnet *un, un->un_pri = kmem_zalloc(sizeof(*un->un_pri), KM_SLEEP); struct usbnet_private * const unp = un->un_pri; - usb_init_task(&unp->unp_ticktask, usbnet_tick_task, un, USB_TASKQ_MPSAFE); + usb_init_task(&unp->unp_mcasttask, usbnet_mcast_task, un, + USB_TASKQ_MPSAFE); + usb_init_task(&unp->unp_ticktask, usbnet_tick_task, un, + USB_TASKQ_MPSAFE); callout_init(&unp->unp_stat_ch, CALLOUT_MPSAFE); callout_setfunc(&unp->unp_stat_ch, usbnet_tick, un); @@ -1506,6 +1562,8 @@ usbnet_detach(device_t self, int flags) callout_halt(&unp->unp_stat_ch, NULL); usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER, NULL); + usb_rem_task_wait(un->un_udev, &unp->unp_mcasttask, USB_TASKQ_DRIVER, + NULL); mutex_enter(&unp->unp_core_lock); unp->unp_refcnt--; @@ -1534,6 +1592,40 @@ usbnet_detach(device_t self, int flags) } usbnet_ec(un)->ec_mii = NULL; + /* + * We have already waited for the multicast task to complete. + * Unfortunately, until if_detach, nothing has prevented it + * from running again -- another thread might issue if_mcast_op + * between the time of our first usb_rem_task_wait and the time + * we actually get around to if_detach. + * + * Fortunately, the first usb_rem_task_wait ensures that if the + * task is scheduled again, it will witness our setting of + * unp_dying to true[*]. So after that point, if the task is + * scheduled again, it will decline to touch IFNET_LOCK and do + * nothing. But we still need to wait for it to complete. + * + * It would be nice if we could write + * + * if_pleasestopissuingmcastopsthanks(ifp); + * usb_rem_task_wait(..., &unp->unp_mcasttask, ...); + * if_detach(ifp); + * + * and then we would need only one usb_rem_task_wait. + * + * Unfortunately, there is no such operation available in + * sys/net at the moment, and it would require a bit of + * coordination with if_mcast_op and doifioctl probably under a + * new lock. So we'll use this kludge until that mechanism is + * invented. + * + * [*] This is not exactly a documented property of the API, + * but it is implied by the single lock in the task queue + * serializing changes to the task state. + */ + usb_rem_task_wait(un->un_udev, &unp->unp_mcasttask, USB_TASKQ_DRIVER, + NULL); + cv_destroy(&unp->unp_detachcv); mutex_destroy(&unp->unp_core_lock); mutex_destroy(&unp->unp_rxlock); From 063f8aa0be69f8c938beaebe138664d71e7cb265 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 24 Dec 2021 22:10:56 +0000 Subject: [PATCH 02/77] usbnet: Simplify usbnet_isdying. usbnet_detach (or its caller) stops all users before it returns. If un->un_pri is null at this point, there's a bug -- something didn't wait for everything to finish before calling usbnet_detach. --- sys/dev/usb/usbnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 9fa061b3cea0..9c694b588346 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1322,7 +1322,7 @@ usbnet_havelink(struct usbnet *un) bool usbnet_isdying(struct usbnet *un) { - return un->un_pri == NULL || un->un_pri->unp_dying; + return un->un_pri->unp_dying; } From 1f6bf1eb7aaa310c86d1448ae043941315e5b3de Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 24 Dec 2021 22:56:01 +0000 Subject: [PATCH 03/77] usbnet: Set and clear IFF_RUNNING slightly earlier and later. - Set IFF_RUNNING before any calls to usbnet_rxeof are possible. - Don't clear IFF_RUNNING until all transfers have been aborted. --- sys/dev/usb/usbnet.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 9c694b588346..1f58ff87f1d3 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -850,9 +850,6 @@ usbnet_init_rx_tx(struct usbnet * const un) goto out; } - /* Start up the receive pipe(s). */ - usbnet_rx_start_pipes(un); - /* Indicate we are up and running. */ #if 0 /* XXX if_mcast_op() can call this without ifnet locked */ @@ -860,6 +857,9 @@ usbnet_init_rx_tx(struct usbnet * const un) #endif ifp->if_flags |= IFF_RUNNING; + /* Start up the receive pipe(s). */ + usbnet_rx_start_pipes(un); + callout_schedule(&unp->unp_stat_ch, hz); out: @@ -1126,14 +1126,6 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) uno_stop(un, ifp, disable); - /* - * XXXSMP Would like to - * KASSERT(IFNET_LOCKED(ifp)) - * here but the locking order is: - * ifnet -> core_lock -> rxlock -> txlock - * and core_lock is already held. - */ - ifp->if_flags &= ~IFF_RUNNING; unp->unp_timer = 0; callout_halt(&unp->unp_stat_ch, &unp->unp_core_lock); @@ -1150,6 +1142,15 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) /* Close pipes. */ usbnet_ep_close_pipes(un); + /* + * XXXSMP Would like to + * KASSERT(IFNET_LOCKED(ifp)) + * here but the locking order is: + * ifnet -> core_lock -> rxlock -> txlock + * and core_lock is already held. + */ + ifp->if_flags &= ~IFF_RUNNING; + usbnet_unbusy(un); } From 3fead99e509c7a62601ec3c20d7397d8454e47f8 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 24 Dec 2021 22:59:10 +0000 Subject: [PATCH 04/77] usbnet: Take IFNET_LOCK around access to if_flags in usbnet_detach. This is not stable without IFNET_LOCK. Extraneous calls to usbnet_stop arising from this race might be harmless, but let's render it unnecessary to even think about that. --- sys/dev/usb/usbnet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 1f58ff87f1d3..d35385f1cdbd 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1554,11 +1554,11 @@ usbnet_detach(device_t self, int flags) unp->unp_dying = true; mutex_exit(&unp->unp_core_lock); + IFNET_LOCK(ifp); if (ifp->if_flags & IFF_RUNNING) { - IFNET_LOCK(ifp); usbnet_if_stop(ifp, 1); - IFNET_UNLOCK(ifp); } + IFNET_UNLOCK(ifp); callout_halt(&unp->unp_stat_ch, NULL); usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER, From 3ecdfc6895572ef5a24fcb95e1e1655d8c1ec7c2 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 24 Dec 2021 23:01:27 +0000 Subject: [PATCH 05/77] usbnet: Ensure ifp->if_softc is initialized _before_ publishing ifp. Otherwise other parts of the system might start using ifp the moment we if_register it, and trip over null if_softc. --- sys/dev/usb/usbnet.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index d35385f1cdbd..83fcf11b7ebc 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -80,6 +80,7 @@ struct usbnet_private { bool unp_dying; bool unp_stopping; bool unp_attached; + bool unp_ifp_attached; bool unp_link; int unp_refcnt; @@ -1492,7 +1493,9 @@ usbnet_attach_ifp(struct usbnet *un, struct ifnet * const ifp = usbnet_ifp(un); KASSERT(unp->unp_attached); + KASSERT(!unp->unp_ifp_attached); + ifp->if_softc = un; strlcpy(ifp->if_xname, device_xname(un->un_dev), IFNAMSIZ); ifp->if_flags = if_flags; ifp->if_extflags = IFEF_MPSAFE | if_extflags; @@ -1511,6 +1514,7 @@ usbnet_attach_ifp(struct usbnet *un, if (ifp->_if_input == NULL) ifp->if_percpuq = if_percpuq_create(ifp); if_register(ifp); + unp->unp_ifp_attached = true; /* * If ethernet address is all zero, skip ether_ifattach() and @@ -1528,7 +1532,6 @@ usbnet_attach_ifp(struct usbnet *un, /* Now ready, and attached. */ IFQ_SET_READY(&ifp->if_snd); - ifp->if_softc = un; usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, un->un_udev, un->un_dev); @@ -1584,7 +1587,7 @@ usbnet_detach(device_t self, int flags) mii_detach(mii, MII_PHY_ANY, MII_OFFSET_ANY); ifmedia_fini(&mii->mii_media); } - if (ifp->if_softc) { + if (unp->unp_ifp_attached) { if (!usbnet_empty_eaddr(un)) ether_ifdetach(ifp); else From fd810018664e5e3b56c6a6afffe16aead70c5c00 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 24 Dec 2021 23:08:03 +0000 Subject: [PATCH 06/77] usbnet: Ensure access to unp_timer is protected by unp_txlock. --- sys/dev/usb/usbnet.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 83fcf11b7ebc..de231d9bd799 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1127,7 +1127,9 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) uno_stop(un, ifp, disable); + mutex_enter(&unp->unp_txlock); unp->unp_timer = 0; + mutex_exit(&unp->unp_txlock); callout_halt(&unp->unp_stat_ch, &unp->unp_core_lock); usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER, @@ -1239,7 +1241,10 @@ usbnet_tick_task(void *arg) usbnet_busy(un); mutex_exit(&unp->unp_core_lock); - if (unp->unp_timer != 0 && --unp->unp_timer == 0) + mutex_enter(&unp->unp_txlock); + const bool timeout = unp->unp_timer != 0 && --unp->unp_timer == 0; + mutex_exit(&unp->unp_txlock); + if (timeout) usbnet_watchdog(ifp); DPRINTFN(8, "mii %#jx ifp %#jx", (uintptr_t)mii, (uintptr_t)ifp, 0, 0); From cc0fbd4ef11f6a7b23511c14138d71c9df1ac407 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 24 Dec 2021 23:34:52 +0000 Subject: [PATCH 07/77] usbnet: Assert IFNET_LOCKED on if_flags change callbacks. - if_init - if_stop - ethersubr(9) ifflags_cb --- sys/dev/usb/usbnet.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index de231d9bd799..c2b0d55a6bc9 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1006,6 +1006,8 @@ usbnet_ifflags_cb(struct ethercom *ec) struct usbnet_private * const unp = un->un_pri; int rv = 0; + KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); + mutex_enter(&unp->unp_core_lock); const u_short changed = ifp->if_flags ^ unp->unp_if_flags; @@ -1163,6 +1165,8 @@ usbnet_if_stop(struct ifnet *ifp, int disable) struct usbnet * const un = ifp->if_softc; struct usbnet_private * const unp = un->un_pri; + KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); + mutex_enter(&unp->unp_core_lock); usbnet_stop(un, ifp, disable); mutex_exit(&unp->unp_core_lock); @@ -1272,6 +1276,8 @@ usbnet_if_init(struct ifnet *ifp) USBNETHIST_FUNC(); USBNETHIST_CALLED(); struct usbnet * const un = ifp->if_softc; + KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); + return uno_init(un, ifp); } From b7190a0889c6eff6ddd29837a77bea0c04fd04e6 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 24 Dec 2021 23:52:41 +0000 Subject: [PATCH 08/77] usbnet: Assert IFNET_LOCKED in usbnet_init_rx_tx, usbnet_stop. Exception: urndis(4) abuses this API to start this logic before the ifp is actually initialized. So for the sake of urndis(4), until sense can be beaten into it, allow the !unp_ifp_attached case to run without IFNET_LOCK. --- sys/dev/usb/usbnet.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index c2b0d55a6bc9..9b475f07ff88 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -151,6 +151,8 @@ fail: static void uno_stop(struct usbnet *un, struct ifnet *ifp, int disable) { + KASSERTMSG(!un->un_pri->unp_ifp_attached || IFNET_LOCKED(ifp), + "%s", ifp->if_xname); usbnet_isowned_core(un); if (un->un_ops->uno_stop) (*un->un_ops->uno_stop)(ifp, disable); @@ -820,6 +822,9 @@ usbnet_init_rx_tx(struct usbnet * const un) usbd_status err; int error = 0; + KASSERTMSG(!unp->unp_ifp_attached || IFNET_LOCKED(ifp), + "%s", ifp->if_xname); + usbnet_isowned_core(un); if (unp->unp_dying) { @@ -1117,6 +1122,8 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) USBNETHIST_FUNC(); USBNETHIST_CALLED(); + KASSERTMSG(!unp->unp_ifp_attached || IFNET_LOCKED(ifp), + "%s", ifp->if_xname); usbnet_isowned_core(un); usbnet_busy(un); @@ -1147,13 +1154,9 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) /* Close pipes. */ usbnet_ep_close_pipes(un); - /* - * XXXSMP Would like to - * KASSERT(IFNET_LOCKED(ifp)) - * here but the locking order is: - * ifnet -> core_lock -> rxlock -> txlock - * and core_lock is already held. - */ + /* Everything is quesced now. */ + KASSERTMSG(!unp->unp_ifp_attached || IFNET_LOCKED(ifp), + "%s", ifp->if_xname); ifp->if_flags &= ~IFF_RUNNING; usbnet_unbusy(un); From e6ec7996ec5c458783560c32ac19d9ec85962a34 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 24 Dec 2021 22:50:37 +0000 Subject: [PATCH 09/77] usbnet: Don't check if_flags for IFF_RUNNING in usbnet_rxeof. This can only run after we start the pipes in usbnet_init_rx_tx, and before we abort the pipes in usbnet_stop, during which time if_flags & IFF_RUNNING is stably set. --- sys/dev/usb/usbnet.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 9b475f07ff88..7123c7c95879 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -337,7 +337,6 @@ usbnet_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 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, "%jd: enter: status %#jx xfer %#jx", @@ -347,7 +346,7 @@ usbnet_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) if (unp->unp_dying || unp->unp_stopping || status == USBD_INVAL || status == USBD_NOT_STARTED || - status == USBD_CANCELLED || !(ifp->if_flags & IFF_RUNNING)) + status == USBD_CANCELLED) goto out; if (status != USBD_NORMAL_COMPLETION) { From caec8228f32ff6cfa0c879fa0c6ae56dd6226627 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 24 Dec 2021 22:52:49 +0000 Subject: [PATCH 10/77] usbnet: Don't check if_flags for IFF_RUNNING in usbnet_pipe_intr. The one user of this interface in tree, aue(4), doesn't care -- if_statinc is safe whether IFF_RUNNING or not. --- sys/dev/usb/usbnet.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 7123c7c95879..846faf9f5404 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -443,11 +443,10 @@ usbnet_pipe_intr(struct usbd_xfer *xfer, void *priv, usbd_status status) struct usbnet * const un = priv; struct usbnet_private * const unp = un->un_pri; struct usbnet_intr * const uni = un->un_intr; - struct ifnet * const ifp = usbnet_ifp(un); if (uni == NULL || unp->unp_dying || unp->unp_stopping || status == USBD_INVAL || status == USBD_NOT_STARTED || - status == USBD_CANCELLED || !(ifp->if_flags & IFF_RUNNING)) { + status == USBD_CANCELLED) { USBNETHIST_CALLARGS("%jd: uni %#jx d/s %#jx status %#jx", unp->unp_number, (uintptr_t)uni, (unp->unp_dying << 8) | unp->unp_stopping, status); From ade0551a5a361fb007961b401c2cc46b677682fc Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 25 Dec 2021 12:52:21 +0000 Subject: [PATCH 11/77] usbnet: Omit needless unp == NULL test in usbnet_tick_task. The task is never scheduled until after un->un_pri is initialized, and un->un_pri isn't nulled until after the callout and task are quiescent. --- sys/dev/usb/usbnet.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 846faf9f5404..e1dca2a3980e 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1227,9 +1227,6 @@ usbnet_tick_task(void *arg) struct usbnet * const un = arg; struct usbnet_private * const unp = un->un_pri; - if (unp == NULL) - return; - USBNETHIST_CALLARGSN(8, "%jd: enter", unp->unp_number, 0, 0, 0); mutex_enter(&unp->unp_core_lock); From 25c151e7329ee1edc6f624438d6ac7000646f33a Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 25 Dec 2021 20:31:02 +0000 Subject: [PATCH 12/77] axen(4), mue(4), smsc(4): Omit irrelevant cases in ioctl. SIOCSIFFLAGS and SIOCSETHERCAP always end up in ether_ioctl_reinit, which triggers the same logic to reprogram the multicast filters anyway. --- sys/dev/usb/if_axen.c | 2 -- sys/dev/usb/if_mue.c | 2 -- sys/dev/usb/if_smsc.c | 2 -- 3 files changed, 6 deletions(-) diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index bf91d56b356d..fe433722d185 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -559,8 +559,6 @@ axen_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) usbnet_busy(un); switch (cmd) { - case SIOCSIFFLAGS: - case SIOCSETHERCAP: case SIOCADDMULTI: case SIOCDELMULTI: axen_setiff_locked(un); diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index 559b9eff2569..16a52e4c6ed4 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1273,8 +1273,6 @@ mue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) usbnet_busy(un); switch (cmd) { - case SIOCSIFFLAGS: - case SIOCSETHERCAP: case SIOCADDMULTI: case SIOCDELMULTI: mue_setiff_locked(un); diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 6cf37e507d1c..12eaf3fa3cc6 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -757,8 +757,6 @@ smsc_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) usbnet_busy(un); switch (cmd) { - case SIOCSIFFLAGS: - case SIOCSETHERCAP: case SIOCADDMULTI: case SIOCDELMULTI: smsc_setiff_locked(un); From 7bb1c749cea613d343325b97791058a715cbb78f Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 26 Dec 2021 00:52:09 +0000 Subject: [PATCH 13/77] usbnet: Remove usbnet_set_dying. Not necessary for the one caller that did it (url(4)): usbnet_detach handles failed attach just fine without it. --- sys/dev/usb/if_url.c | 8 +------- sys/dev/usb/usbnet.c | 6 ------ sys/dev/usb/usbnet.h | 1 - 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index 764b9c654682..dbb57bf66ca7 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -256,18 +256,12 @@ url_attach(device_t parent, device_t self, void *aux) usbnet_unlock_core(un); if (err) { aprint_error_dev(self, "read MAC address failed\n"); - goto bad; + return; } /* initialize interface information */ usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 0, &unm); - - return; - - bad: - usbnet_set_dying(un, true); - return; } /* read/write memory */ diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index e1dca2a3980e..a8f912b0ad54 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1288,12 +1288,6 @@ usbnet_set_link(struct usbnet *un, bool link) un->un_pri->unp_link = link; } -void -usbnet_set_dying(struct usbnet *un, bool link) -{ - un->un_pri->unp_dying = link; -} - struct ifnet * usbnet_ifp(struct usbnet *un) { diff --git a/sys/dev/usb/usbnet.h b/sys/dev/usb/usbnet.h index 15e9dfc7b351..1faa822887c5 100644 --- a/sys/dev/usb/usbnet.h +++ b/sys/dev/usb/usbnet.h @@ -284,7 +284,6 @@ struct usbnet { /* Various accessors. */ void usbnet_set_link(struct usbnet *, bool); -void usbnet_set_dying(struct usbnet *, bool); struct ifnet *usbnet_ifp(struct usbnet *); struct ethercom *usbnet_ec(struct usbnet *); From a74f0b39f4d76569dd62fbc4ab371107e7c21323 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 26 Dec 2021 01:17:06 +0000 Subject: [PATCH 14/77] usbnet: Fix ordering of actions in usbnet_stop. Make sure all software activity is quiescent (callouts and tasks, including ifmedia and mii callbacks -- anything that might trigger register access) before asking the driver to stop the hardware. This way, the driver uno_stop routine is guaranteed exclusive access to the registers. This will also enable us to simplify the callouts and tasks so they don't have to check the software state -- to be done in a separate commit. --- sys/dev/usb/usbnet.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index a8f912b0ad54..1b516402527d 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1132,16 +1132,29 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) mutex_exit(&unp->unp_txlock); mutex_exit(&unp->unp_rxlock); + /* + * Stop the timer first, then the task -- if the timer was + * already firing, we stop the task or wait for it complete + * only after if last fired. Setting unp_stopping prevents the + * timer task from being scheduled again. + */ + callout_halt(&unp->unp_stat_ch, &unp->unp_core_lock); + usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER, + &unp->unp_core_lock); + + /* + * Now that the software is quiescent, ask the driver to stop + * the hardware. The driver's uno_stop routine now has + * exclusive access to any registers that might previously have + * been used by to ifmedia, mii, or ioctl callbacks. + */ uno_stop(un, ifp, disable); + /* Clear the watchdog timer. */ mutex_enter(&unp->unp_txlock); unp->unp_timer = 0; mutex_exit(&unp->unp_txlock); - callout_halt(&unp->unp_stat_ch, &unp->unp_core_lock); - usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER, - &unp->unp_core_lock); - /* Stop transfers. */ usbnet_ep_stop_pipes(un); From 3fed127492d50ff87fd972c137f7a1c36f5c9ad4 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 26 Dec 2021 01:22:46 +0000 Subject: [PATCH 15/77] usbnet: Assert IFNET_LOCKED in usbnet_media_upd. This ensures, if the device is being initialized or stopped, usbnet_media_upd will not run until it's done, so the reset sequence has exclusive access to the device registers used by mii. --- sys/dev/usb/usbnet.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 1b516402527d..89041f6ec949 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -983,6 +983,9 @@ usbnet_media_upd(struct ifnet *ifp) /* ifmedia layer ensures core_lock is held. */ usbnet_isowned_core(un); + /* ifmedia changes only with IFNET_LOCK held. */ + KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); + if (unp->unp_dying) return EIO; From d56b8e5782867b99591bbce5e6e090c2d0b12e8d Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 26 Dec 2021 01:29:16 +0000 Subject: [PATCH 16/77] usbnet: Refuse to bring interfaces back up once dying. Make this happen uniformly across all usbnet drivers, not on a per-driver basis. This ensures new activity on the interface can't happen by the time we have stopped existing activity and waited for it to complete. --- sys/dev/usb/usbnet.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 89041f6ec949..a831fc6eba62 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1289,9 +1289,20 @@ usbnet_if_init(struct ifnet *ifp) { USBNETHIST_FUNC(); USBNETHIST_CALLED(); struct usbnet * const un = ifp->if_softc; + bool dying; KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); + /* + * Prevent anyone from bringing the interface back up once + * we're detaching. + */ + mutex_enter(&un->un_pri->unp_core_lock); + dying = un->un_pri->unp_dying; + mutex_exit(&un->un_pri->unp_core_lock); + if (dying) + return EIO; + return uno_init(un, ifp); } @@ -1572,10 +1583,18 @@ usbnet_detach(device_t self, int flags) struct ifnet * const ifp = usbnet_ifp(un); struct mii_data * const mii = usbnet_mii(un); + /* + * Prevent new activity. After we stop the interface, it + * cannot be brought back up. + */ mutex_enter(&unp->unp_core_lock); unp->unp_dying = true; mutex_exit(&unp->unp_core_lock); + /* + * If we're still running on the network, stop and wait for all + * asynchronous activity to finish. + */ IFNET_LOCK(ifp); if (ifp->if_flags & IFF_RUNNING) { usbnet_if_stop(ifp, 1); From 1d9fa4ad4b63db37d597fe97844c9afc0ce65f7e Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 26 Dec 2021 01:32:42 +0000 Subject: [PATCH 17/77] usbnet: Omit needless callout_halt and usb_rem_task_wait. The callout and tasks cannot be pending at this point -- it is a bug if usbnet_if_stop failed to quiesce everything, so turn these into KASSERTs. --- sys/dev/usb/usbnet.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index a831fc6eba62..630290b91626 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1601,9 +1601,13 @@ usbnet_detach(device_t self, int flags) } IFNET_UNLOCK(ifp); - callout_halt(&unp->unp_stat_ch, NULL); - usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER, - NULL); + /* + * The callout and tick task can't be scheduled anew at this + * point, and usbnet_if_stop has waited for them to complete. + */ + KASSERT(!callout_pending(&unp->unp_stat_ch)); + KASSERT(!usb_task_pending(un->un_udev, &unp->unp_ticktask)); + usb_rem_task_wait(un->un_udev, &unp->unp_mcasttask, USB_TASKQ_DRIVER, NULL); From fc28ad5596edecd8599845c11da553bb574e708e Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 26 Dec 2021 01:47:10 +0000 Subject: [PATCH 18/77] usbnet: Detach interface and mii before waiting for refcnt to drain. All outstanding software activity under usbnet's control -- which is all that participates in the refcnting -- should be quiesced by stopping and detaching everything. --- sys/dev/usb/usbnet.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 630290b91626..f072bebc9e83 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1611,20 +1611,6 @@ usbnet_detach(device_t self, int flags) usb_rem_task_wait(un->un_udev, &unp->unp_mcasttask, USB_TASKQ_DRIVER, NULL); - mutex_enter(&unp->unp_core_lock); - unp->unp_refcnt--; - while (unp->unp_refcnt >= 0) { - /* Wait for processes to go away */ - cv_wait(&unp->unp_detachcv, &unp->unp_core_lock); - } - mutex_exit(&unp->unp_core_lock); - - usbnet_rx_list_free(un); - usbnet_tx_list_free(un); - - callout_destroy(&unp->unp_stat_ch); - rnd_detach_source(&unp->unp_rndsrc); - if (mii) { mii_detach(mii, MII_PHY_ANY, MII_OFFSET_ANY); ifmedia_fini(&mii->mii_media); @@ -1672,6 +1658,20 @@ usbnet_detach(device_t self, int flags) usb_rem_task_wait(un->un_udev, &unp->unp_mcasttask, USB_TASKQ_DRIVER, NULL); + mutex_enter(&unp->unp_core_lock); + unp->unp_refcnt--; + while (unp->unp_refcnt >= 0) { + /* Wait for processes to go away */ + cv_wait(&unp->unp_detachcv, &unp->unp_core_lock); + } + mutex_exit(&unp->unp_core_lock); + + usbnet_rx_list_free(un); + usbnet_tx_list_free(un); + + callout_destroy(&unp->unp_stat_ch); + rnd_detach_source(&unp->unp_rndsrc); + cv_destroy(&unp->unp_detachcv); mutex_destroy(&unp->unp_core_lock); mutex_destroy(&unp->unp_rxlock); From 602aa9b09f1aba403c8bee2fbc87acbd8df0ee84 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 26 Dec 2021 01:49:56 +0000 Subject: [PATCH 19/77] usbnet: Make detach order reverse attach order, for unp_stat_ch. No functional change intended. --- sys/dev/usb/usbnet.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index f072bebc9e83..470db472a7c5 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1669,7 +1669,6 @@ usbnet_detach(device_t self, int flags) usbnet_rx_list_free(un); usbnet_tx_list_free(un); - callout_destroy(&unp->unp_stat_ch); rnd_detach_source(&unp->unp_rndsrc); cv_destroy(&unp->unp_detachcv); @@ -1677,6 +1676,8 @@ usbnet_detach(device_t self, int flags) mutex_destroy(&unp->unp_rxlock); mutex_destroy(&unp->unp_txlock); + callout_destroy(&unp->unp_stat_ch); + pmf_device_deregister(un->un_dev); usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, un->un_udev, un->un_dev); From 44a8982df486895ebfe9e496bf42655cb09ab28b Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 26 Dec 2021 01:50:32 +0000 Subject: [PATCH 20/77] usbnet: Don't issue a detach event if we never issued an attach one. --- sys/dev/usb/usbnet.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 470db472a7c5..33c78dcc85d9 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1680,7 +1680,14 @@ usbnet_detach(device_t self, int flags) pmf_device_deregister(un->un_dev); - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, un->un_udev, un->un_dev); + /* + * Notify userland that we're going away, if we arrived in the + * first place. + */ + if (unp->unp_ifp_attached) { + usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, un->un_udev, + un->un_dev); + } kmem_free(unp, sizeof(*unp)); un->un_pri = NULL; From 2c69fb773c9ceffe702615900858581a08d97290 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 26 Dec 2021 01:50:59 +0000 Subject: [PATCH 21/77] usbnet: Uncomment and fix assertion for ifp->if_flags |= IFF_RUNNING. We always hold IFNET_LOCK for ioctls that end up here -- the ones that don't hold it are only SIOCADDMULTI/SIOCDELMULTI, which don't end up here. However, urndis(4) throws a spanner in the works by doing weird device initialization. --- sys/dev/usb/usbnet.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 33c78dcc85d9..b3ad4ba90f01 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -855,10 +855,9 @@ usbnet_init_rx_tx(struct usbnet * const un) } /* Indicate we are up and running. */ -#if 0 - /* XXX if_mcast_op() can call this without ifnet locked */ - KASSERT(ifp->if_softc == NULL || IFNET_LOCKED(ifp)); -#endif + /* XXX urndis calls usbnet_init_rx_tx before usbnet_attach_ifp. */ + KASSERTMSG(!unp->unp_ifp_attached || IFNET_LOCKED(ifp), + "%s", ifp->if_xname); ifp->if_flags |= IFF_RUNNING; /* Start up the receive pipe(s). */ From 05c963c3323a51bd65d892bff731f11f93752a4d Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 24 Dec 2021 22:07:39 +0000 Subject: [PATCH 22/77] usbnet: Omit needless tests in usbnet_tick. It's harmless for us to schedule the tick task even if unp_dying or unp_stopping is set by now, because usbnet_stop will just wait for it to finish anyway, and the callout can't be scheduled again until the interface is done stopping and is brought back up again. No need for unp == NULL test -- un->un_pri is initialized well before this callout can be scheduled, and is nulled out only at the end of usbnet_detach, at which point we have already halted this callout. --- sys/dev/usb/usbnet.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index b3ad4ba90f01..183bd5af37c6 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1203,10 +1203,8 @@ usbnet_tick(void *arg) USBNETHIST_CALLARGSN(10, "%jd: enter", unp->unp_number, 0, 0, 0); - if (unp != NULL && !unp->unp_stopping && !unp->unp_dying) { - /* Perform periodic stuff in process context */ - usb_add_task(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER); - } + /* Perform periodic stuff in process context */ + usb_add_task(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER); } static void From 79331a987d9d1d2a3c03b7a80219c4c218adef25 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 26 Dec 2021 01:54:38 +0000 Subject: [PATCH 23/77] usbnet: Omit needless locking/busying/testing in usbnet_tick_task. usbnet_stop waits for the task to complete before resetting the hardware, and usbnet_detach waits for usbnet_stop to complete before destroying anything, so there's no need for any of this. --- sys/dev/usb/usbnet.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 183bd5af37c6..4568379f0db7 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1239,22 +1239,10 @@ usbnet_tick_task(void *arg) USBNETHIST_FUNC(); struct usbnet * const un = arg; struct usbnet_private * const unp = un->un_pri; - - USBNETHIST_CALLARGSN(8, "%jd: enter", unp->unp_number, 0, 0, 0); - - mutex_enter(&unp->unp_core_lock); - if (unp->unp_stopping || unp->unp_dying) { - mutex_exit(&unp->unp_core_lock); - return; - } - struct ifnet * const ifp = usbnet_ifp(un); struct mii_data * const mii = usbnet_mii(un); - KASSERT(ifp != NULL); /* embedded member */ - - usbnet_busy(un); - mutex_exit(&unp->unp_core_lock); + USBNETHIST_CALLARGSN(8, "%jd: enter", unp->unp_number, 0, 0, 0); mutex_enter(&unp->unp_txlock); const bool timeout = unp->unp_timer != 0 && --unp->unp_timer == 0; @@ -1275,7 +1263,6 @@ usbnet_tick_task(void *arg) uno_tick(un); mutex_enter(&unp->unp_core_lock); - usbnet_unbusy(un); if (!unp->unp_stopping && !unp->unp_dying) callout_schedule(&unp->unp_stat_ch, hz); mutex_exit(&unp->unp_core_lock); From 0d9fa4a409c2f3d03732c574f47d67ce08afa034 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 26 Dec 2021 10:06:50 +0000 Subject: [PATCH 24/77] usbnet: Clear watchdog timer before stopping hardware. No need to take the lock again -- which might not be necessary because the callout and task have completed, but let's obviate the need to think about that. --- sys/dev/usb/usbnet.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 4568379f0db7..a84512b557e4 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1128,9 +1128,14 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) usbnet_busy(un); + /* + * Prevent new activity (rescheduling ticks, xfers, &c.) and + * clear the watchdog timer. + */ mutex_enter(&unp->unp_rxlock); mutex_enter(&unp->unp_txlock); unp->unp_stopping = true; + unp->unp_timer = 0; mutex_exit(&unp->unp_txlock); mutex_exit(&unp->unp_rxlock); @@ -1152,11 +1157,6 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) */ uno_stop(un, ifp, disable); - /* Clear the watchdog timer. */ - mutex_enter(&unp->unp_txlock); - unp->unp_timer = 0; - mutex_exit(&unp->unp_txlock); - /* Stop transfers. */ usbnet_ep_stop_pipes(un); From c39648baa8ed25fc092603402693d2c8c99b43df Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Wed, 29 Dec 2021 22:34:05 +0000 Subject: [PATCH 25/77] usbnet: Avoid IFNET_LOCK on detach if we never attached the ifp. --- sys/dev/usb/usbnet.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index a84512b557e4..22b87068e38d 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1578,12 +1578,17 @@ usbnet_detach(device_t self, int flags) /* * If we're still running on the network, stop and wait for all * asynchronous activity to finish. + * + * If usbnet_attach_ifp never ran, IFNET_LOCK won't work, but + * no activity is possible, so just skip this part. */ - IFNET_LOCK(ifp); - if (ifp->if_flags & IFF_RUNNING) { - usbnet_if_stop(ifp, 1); + if (unp->unp_ifp_attached) { + IFNET_LOCK(ifp); + if (ifp->if_flags & IFF_RUNNING) { + usbnet_if_stop(ifp, 1); + } + IFNET_UNLOCK(ifp); } - IFNET_UNLOCK(ifp); /* * The callout and tick task can't be scheduled anew at this From e6f6fc068e3bd13f67b78706fff4dc5cef82a186 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 09:34:22 +0000 Subject: [PATCH 26/77] cue(4): Return real error code, not -1, on init when detaching. --- sys/dev/usb/if_cue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index e730297a939d..587c430a5d15 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -622,7 +622,7 @@ cue_init_locked(struct ifnet *ifp) DPRINTFN(10,("%s: %s: enter\n", device_xname(un->un_dev),__func__)); if (usbnet_isdying(un)) - return -1; + return ENXIO; /* Cancel pending I/O */ usbnet_stop(un, ifp, 1); From c85cbaa48d796562102cf34fe049eb3a434cee96 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 09:48:31 +0000 Subject: [PATCH 27/77] usbnet: Don't waste time calling uno_stop if device is detaching. The hardware is most likely gone, so trying to write to its registers (and, in some cases, wait until a timeout for a device to reset) is a waste of time. Even if it was detached only in software with drvctl, reattaching it will reset the device anyway. --- sys/dev/usb/usbnet.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 22b87068e38d..e04c3589f2b5 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1154,8 +1154,13 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) * the hardware. The driver's uno_stop routine now has * exclusive access to any registers that might previously have * been used by to ifmedia, mii, or ioctl callbacks. + * + * Don't bother if the device is being detached, though -- if + * it's been unplugged then there's no point in trying to touch + * the registers. */ - uno_stop(un, ifp, disable); + if (!unp->unp_dying) + uno_stop(un, ifp, disable); /* Stop transfers. */ usbnet_ep_stop_pipes(un); From db90f97f831f610c4480c497e56918a440879507 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 09:51:35 +0000 Subject: [PATCH 28/77] usbnet: Impart blame on whose ifnet is unlocked in uno_init. --- sys/dev/usb/usbnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index e04c3589f2b5..b938c70a8202 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -181,7 +181,7 @@ uno_override_ioctl(struct usbnet *un, struct ifnet *ifp, u_long cmd, void *data) static int uno_init(struct usbnet *un, struct ifnet *ifp) { - KASSERT(IFNET_LOCKED(ifp)); + KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); return (*un->un_ops->uno_init)(ifp); } From 358ce573f8053d8129de56d6587a6635ed09f8c9 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 09:53:09 +0000 Subject: [PATCH 29/77] usbnet: Assert ioctl locking. --- sys/dev/usb/usbnet.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index b938c70a8202..ace8f78da9d6 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -161,11 +161,15 @@ uno_stop(struct usbnet *un, struct ifnet *ifp, int disable) static int uno_ioctl(struct usbnet *un, struct ifnet *ifp, u_long cmd, void *data) { - /* - * There are cases where IFNET_LOCK will not be held when we - * are called (e.g. add/delete multicast address), so we can't - * assert it. - */ + + switch (cmd) { + case SIOCADDMULTI: + case SIOCDELMULTI: + break; + default: + KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); + } + if (un->un_ops->uno_ioctl) return (*un->un_ops->uno_ioctl)(ifp, cmd, data); return 0; @@ -174,7 +178,15 @@ uno_ioctl(struct usbnet *un, struct ifnet *ifp, u_long cmd, void *data) static int uno_override_ioctl(struct usbnet *un, struct ifnet *ifp, u_long cmd, void *data) { - /* See above. */ + + switch (cmd) { + case SIOCADDMULTI: + case SIOCDELMULTI: + break; + default: + KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); + } + return (*un->un_ops->uno_override_ioctl)(ifp, cmd, data); } From 3593065fe2b6fc57c7cf78b32d4410e47f5ac9b3 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 10:17:02 +0000 Subject: [PATCH 30/77] usbnet: Enter uno_init with the core lock held. This reduces code in all drivers except urndis(4) and aue(4). However, it's still safe for urndis to drop the core lock because the ifnet is locked, and the ifnet lock covers the DOWN->UP (uno_init) and UP->DOWN (uno_stop) transitions. --- sys/dev/usb/if_aue.c | 5 +++-- sys/dev/usb/if_axe.c | 2 -- sys/dev/usb/if_axen.c | 2 -- sys/dev/usb/if_cdce.c | 2 -- sys/dev/usb/if_cue.c | 2 -- sys/dev/usb/if_kue.c | 2 -- sys/dev/usb/if_mos.c | 2 -- sys/dev/usb/if_mue.c | 2 -- sys/dev/usb/if_smsc.c | 2 -- sys/dev/usb/if_udav.c | 5 ----- sys/dev/usb/if_upl.c | 2 -- sys/dev/usb/if_ure.c | 2 -- sys/dev/usb/if_url.c | 2 -- sys/dev/usb/if_urndis.c | 9 ++++++++- sys/dev/usb/usbnet.c | 7 ++++++- 15 files changed, 17 insertions(+), 31 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index 89e2c5f55447..b72eff0349c4 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -1000,11 +1000,9 @@ aue_uno_init(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; int rv; - usbnet_lock_core(un); usbnet_busy(un); rv = aue_init_locked(ifp); usbnet_unbusy(un); - usbnet_unlock_core(un); return rv; } @@ -1012,6 +1010,7 @@ aue_uno_init(struct ifnet *ifp) static int aue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) { + struct usbnet * const un = ifp->if_softc; AUEHIST_FUNC(); AUEHIST_CALLARGSN(5, "aue%jd: enter cmd %#jx data %#jx", @@ -1021,7 +1020,9 @@ aue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) switch (cmd) { case SIOCADDMULTI: case SIOCDELMULTI: + usbnet_lock_core(un); aue_uno_init(ifp); + usbnet_unlock_core(un); break; default: break; diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index eba67386e770..78a4a6546f70 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -1317,11 +1317,9 @@ axe_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); usbnet_busy(un); int ret = axe_init_locked(ifp); usbnet_unbusy(un); - usbnet_unlock_core(un); return ret; } diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index fe433722d185..7d90fa1259f9 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -935,11 +935,9 @@ axen_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); usbnet_busy(un); int ret = axen_init_locked(ifp); usbnet_unbusy(un); - usbnet_unlock_core(un); return ret; } diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c index 3edf73d856ca..4785d9a4cc9e 100644 --- a/sys/dev/usb/if_cdce.c +++ b/sys/dev/usb/if_cdce.c @@ -261,7 +261,6 @@ cdce_uno_init(struct ifnet *ifp) struct usbnet *un = ifp->if_softc; int rv; - usbnet_lock_core(un); if (usbnet_isdying(un)) rv = EIO; else { @@ -269,7 +268,6 @@ cdce_uno_init(struct ifnet *ifp) rv = usbnet_init_rx_tx(un); usbnet_set_link(un, rv == 0); } - usbnet_unlock_core(un); return rv; } diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index 587c430a5d15..191f31eb9eca 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -673,11 +673,9 @@ cue_uno_init(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; int rv; - usbnet_lock_core(un); usbnet_busy(un); rv = cue_init_locked(ifp); usbnet_unbusy(un); - usbnet_unlock_core(un); return rv; } diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index 172bc93fa301..6d8af3cd0735 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -633,11 +633,9 @@ kue_uno_init(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; int rv; - usbnet_lock_core(un); usbnet_busy(un); rv = kue_init_locked(ifp); usbnet_unbusy(un); - usbnet_unlock_core(un); return rv; } diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index 347104b7b0df..987bb0484710 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -760,11 +760,9 @@ mos_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); usbnet_busy(un); int ret = mos_init_locked(ifp); usbnet_unbusy(un); - usbnet_unlock_core(un); return ret; } diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index 16a52e4c6ed4..81534e865688 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1255,11 +1255,9 @@ mue_uno_init(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; int rv; - usbnet_lock_core(un); usbnet_busy(un); rv = mue_init_locked(ifp); usbnet_unbusy(un); - usbnet_unlock_core(un); return rv; } diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 12eaf3fa3cc6..4361532efc39 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -552,11 +552,9 @@ smsc_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); usbnet_busy(un); int ret = smsc_init_locked(ifp); usbnet_unbusy(un); - usbnet_unlock_core(un); return ret; } diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index a38a83a53df0..e22e1f305876 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -478,10 +478,7 @@ udav_uno_init(struct ifnet *ifp) DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - usbnet_lock_core(un); - if (usbnet_isdying(un)) { - usbnet_unlock_core(un); return EIO; } @@ -522,7 +519,6 @@ udav_uno_init(struct ifnet *ifp) if (rc != 0) { usbnet_unbusy(un); - usbnet_unlock_core(un); return rc; } @@ -532,7 +528,6 @@ udav_uno_init(struct ifnet *ifp) rc = usbnet_init_rx_tx(un); usbnet_unbusy(un); - usbnet_unlock_core(un); return rc; } diff --git a/sys/dev/usb/if_upl.c b/sys/dev/usb/if_upl.c index fb99702f160e..cf4ba9de209f 100644 --- a/sys/dev/usb/if_upl.c +++ b/sys/dev/usb/if_upl.c @@ -257,12 +257,10 @@ upl_uno_init(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; int rv; - usbnet_lock_core(un); if (usbnet_isdying(un)) rv = EIO; else rv = usbnet_init_rx_tx(un); - usbnet_unlock_core(un); return rv; } diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index ea5b3023dd31..db75961fc88e 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -456,11 +456,9 @@ ure_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); usbnet_busy(un); int ret = ure_init_locked(ifp); usbnet_unbusy(un); - usbnet_unlock_core(un); return ret; } diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index dbb57bf66ca7..af766fcd455d 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -408,11 +408,9 @@ url_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); usbnet_busy(un); int ret = url_init_locked(ifp); usbnet_unbusy(un); - usbnet_unlock_core(un); return ret; } diff --git a/sys/dev/usb/if_urndis.c b/sys/dev/usb/if_urndis.c index 381207450d72..ff4da0414739 100644 --- a/sys/dev/usb/if_urndis.c +++ b/sys/dev/usb/if_urndis.c @@ -883,8 +883,15 @@ static int urndis_uno_init(struct ifnet *ifp) { struct usbnet *un = ifp->if_softc; + int error; - return urndis_init_un(ifp, un); + KASSERT(IFNET_LOCKED(ifp)); + + usbnet_unlock_core(un); + error = urndis_init_un(ifp, un); + usbnet_lock_core(un); + + return error; } static int diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index ace8f78da9d6..80db2a9464a5 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1291,6 +1291,7 @@ usbnet_if_init(struct ifnet *ifp) USBNETHIST_FUNC(); USBNETHIST_CALLED(); struct usbnet * const un = ifp->if_softc; bool dying; + int error; KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); @@ -1304,7 +1305,11 @@ usbnet_if_init(struct ifnet *ifp) if (dying) return EIO; - return uno_init(un, ifp); + mutex_enter(&un->un_pri->unp_core_lock); + error = uno_init(un, ifp); + mutex_exit(&un->un_pri->unp_core_lock); + + return error; } From 3f7878422b89d42ea3c3aac5de057f1b832efb35 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 26 Dec 2021 01:56:30 +0000 Subject: [PATCH 31/77] usbnet: Print diagnostic about refcnt stragglers. I don't think there can be any, but this message, if printed, would falsify my hypothesis! --- sys/dev/usb/usbnet.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 80db2a9464a5..784f8459b801 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1671,6 +1671,10 @@ usbnet_detach(device_t self, int flags) mutex_enter(&unp->unp_core_lock); unp->unp_refcnt--; + if (unp->unp_refcnt >= 0) { + aprint_error_dev(un->un_dev, "%d stragglers\n", + unp->unp_refcnt + 1); + } while (unp->unp_refcnt >= 0) { /* Wait for processes to go away */ cv_wait(&unp->unp_detachcv, &unp->unp_core_lock); From a771333bf26bc1aa8fcc095085ba653e216eb03a Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 11:51:41 +0000 Subject: [PATCH 32/77] 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). --- sys/dev/usb/usbnet.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 784f8459b801..4b78d50f9247 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -77,7 +77,7 @@ struct usbnet_private { struct callout unp_stat_ch; struct usbd_pipe *unp_ep[USBNET_ENDPT_MAX]; - bool unp_dying; + volatile bool unp_dying; bool unp_stopping; bool unp_attached; bool unp_ifp_attached; @@ -356,7 +356,7 @@ usbnet_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) mutex_enter(&unp->unp_rxlock); - if (unp->unp_dying || unp->unp_stopping || + if (usbnet_isdying(un) || unp->unp_stopping || status == USBD_INVAL || status == USBD_NOT_STARTED || status == USBD_CANCELLED) goto out; @@ -383,7 +383,7 @@ usbnet_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) usbnet_isowned_rx(un); done: - if (unp->unp_dying || unp->unp_stopping) + if (usbnet_isdying(un) || unp->unp_stopping) goto out; mutex_exit(&unp->unp_rxlock); @@ -412,7 +412,7 @@ usbnet_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) unp->unp_number, status, (uintptr_t)xfer, 0); mutex_enter(&unp->unp_txlock); - if (unp->unp_stopping || unp->unp_dying) { + if (unp->unp_stopping || usbnet_isdying(un)) { mutex_exit(&unp->unp_txlock); return; } @@ -456,12 +456,12 @@ usbnet_pipe_intr(struct usbd_xfer *xfer, void *priv, usbd_status status) struct usbnet_private * const unp = un->un_pri; struct usbnet_intr * const uni = un->un_intr; - if (uni == NULL || unp->unp_dying || unp->unp_stopping || + if (uni == NULL || usbnet_isdying(un) || unp->unp_stopping || status == USBD_INVAL || status == USBD_NOT_STARTED || status == USBD_CANCELLED) { USBNETHIST_CALLARGS("%jd: uni %#jx d/s %#jx status %#jx", unp->unp_number, (uintptr_t)uni, - (unp->unp_dying << 8) | unp->unp_stopping, status); + (usbnet_isdying(un) << 8) | unp->unp_stopping, status); return; } @@ -837,7 +837,7 @@ usbnet_init_rx_tx(struct usbnet * const un) usbnet_isowned_core(un); - if (unp->unp_dying) { + if (usbnet_isdying(un)) { return EIO; } @@ -918,13 +918,12 @@ usbnet_mii_readreg(device_t dev, int phy, int reg, uint16_t *val) { USBNETHIST_FUNC(); struct usbnet * const un = device_private(dev); - struct usbnet_private * const unp = un->un_pri; int err; /* MII layer ensures core_lock is held. */ usbnet_isowned_core(un); - if (unp->unp_dying) { + if (usbnet_isdying(un)) { return EIO; } @@ -934,7 +933,7 @@ usbnet_mii_readreg(device_t dev, int phy, int reg, uint16_t *val) if (err) { USBNETHIST_CALLARGS("%jd: read PHY failed: %jd", - unp->unp_number, err, 0, 0); + un->un_pri->unp_number, err, 0, 0); return err; } @@ -946,13 +945,12 @@ usbnet_mii_writereg(device_t dev, int phy, int reg, uint16_t val) { USBNETHIST_FUNC(); struct usbnet * const un = device_private(dev); - struct usbnet_private * const unp = un->un_pri; int err; /* MII layer ensures core_lock is held. */ usbnet_isowned_core(un); - if (unp->unp_dying) { + if (usbnet_isdying(un)) { return EIO; } @@ -962,7 +960,7 @@ usbnet_mii_writereg(device_t dev, int phy, int reg, uint16_t val) if (err) { USBNETHIST_CALLARGS("%jd: write PHY failed: %jd", - unp->unp_number, err, 0, 0); + un->un_pri->unp_number, err, 0, 0); return err; } @@ -997,7 +995,7 @@ usbnet_media_upd(struct ifnet *ifp) /* ifmedia changes only with IFNET_LOCK held. */ KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); - if (unp->unp_dying) + if (usbnet_isdying(un)) return EIO; unp->unp_link = false; @@ -1085,7 +1083,7 @@ usbnet_mcast_task(void *arg) USBNETHIST_CALLARGSN(10, "%jd: enter", unp->unp_number, 0, 0, 0); /* - * If we're detaching, we must check unp_dying _before_ + * If we're detaching, we must check usbnet_isdying _before_ * touching IFNET_LOCK -- the ifnet may have been detached by * the time this task runs. This is racy -- unp_dying may be * set immediately after we test it -- but nevertheless safe, @@ -1094,7 +1092,7 @@ usbnet_mcast_task(void *arg) * IFNET_LOCK after if_detach. See usbnet_detach for details. */ mutex_enter(&unp->unp_core_lock); - dying = unp->unp_dying; + dying = usbnet_isdying(un); mutex_exit(&unp->unp_core_lock); if (dying) return; @@ -1171,7 +1169,7 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) * it's been unplugged then there's no point in trying to touch * the registers. */ - if (!unp->unp_dying) + if (!usbnet_isdying(un)) uno_stop(un, ifp, disable); /* Stop transfers. */ @@ -1280,7 +1278,7 @@ usbnet_tick_task(void *arg) uno_tick(un); mutex_enter(&unp->unp_core_lock); - if (!unp->unp_stopping && !unp->unp_dying) + if (!unp->unp_stopping && !usbnet_isdying(un)) callout_schedule(&unp->unp_stat_ch, hz); mutex_exit(&unp->unp_core_lock); } @@ -1300,7 +1298,7 @@ usbnet_if_init(struct ifnet *ifp) * we're detaching. */ mutex_enter(&un->un_pri->unp_core_lock); - dying = un->un_pri->unp_dying; + dying = usbnet_isdying(un); mutex_exit(&un->un_pri->unp_core_lock); if (dying) return EIO; @@ -1360,7 +1358,7 @@ usbnet_havelink(struct usbnet *un) bool usbnet_isdying(struct usbnet *un) { - return un->un_pri->unp_dying; + return atomic_load_relaxed(&un->un_pri->unp_dying); } @@ -1594,7 +1592,7 @@ usbnet_detach(device_t self, int flags) * cannot be brought back up. */ mutex_enter(&unp->unp_core_lock); - unp->unp_dying = true; + atomic_store_relaxed(&unp->unp_dying, true); mutex_exit(&unp->unp_core_lock); /* @@ -1723,7 +1721,7 @@ usbnet_activate(device_t self, devact_t act) if_deactivate(ifp); mutex_enter(&unp->unp_core_lock); - unp->unp_dying = true; + atomic_store_relaxed(&unp->unp_dying, true); mutex_exit(&unp->unp_core_lock); mutex_enter(&unp->unp_rxlock); From f6b9332dfc6d68174dc2c93a3c37d49538874b89 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 12:23:28 +0000 Subject: [PATCH 33/77] usbnet: Omit needless locking around usbnet_isdying. Now that is tested and set with atomic_load/store, there is no need to hold the lock -- which means we can set it while the core lock is held during, e.g., a reset sequence, and use that to interrupt the sequence so it doesn't get stuck waiting to time out when the device is physically removed. --- sys/dev/usb/usbnet.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 4b78d50f9247..4ea0859904b9 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1075,12 +1075,11 @@ usbnet_mcast_task(void *arg) { USBNETHIST_FUNC(); struct usbnet * const un = arg; - struct usbnet_private * const unp = un->un_pri; struct ifnet * const ifp = usbnet_ifp(un); - bool dying; struct ifreq ifr; - USBNETHIST_CALLARGSN(10, "%jd: enter", unp->unp_number, 0, 0, 0); + USBNETHIST_CALLARGSN(10, "%jd: enter", + un->un_pri->unp_number, 0, 0, 0); /* * If we're detaching, we must check usbnet_isdying _before_ @@ -1091,10 +1090,7 @@ usbnet_mcast_task(void *arg) * issuing if_detach, and necessary, so that we don't touch * IFNET_LOCK after if_detach. See usbnet_detach for details. */ - mutex_enter(&unp->unp_core_lock); - dying = usbnet_isdying(un); - mutex_exit(&unp->unp_core_lock); - if (dying) + if (usbnet_isdying(un)) return; /* @@ -1288,7 +1284,6 @@ usbnet_if_init(struct ifnet *ifp) { USBNETHIST_FUNC(); USBNETHIST_CALLED(); struct usbnet * const un = ifp->if_softc; - bool dying; int error; KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); @@ -1297,10 +1292,7 @@ usbnet_if_init(struct ifnet *ifp) * Prevent anyone from bringing the interface back up once * we're detaching. */ - mutex_enter(&un->un_pri->unp_core_lock); - dying = usbnet_isdying(un); - mutex_exit(&un->un_pri->unp_core_lock); - if (dying) + if (usbnet_isdying(un)) return EIO; mutex_enter(&un->un_pri->unp_core_lock); @@ -1591,9 +1583,7 @@ usbnet_detach(device_t self, int flags) * Prevent new activity. After we stop the interface, it * cannot be brought back up. */ - mutex_enter(&unp->unp_core_lock); atomic_store_relaxed(&unp->unp_dying, true); - mutex_exit(&unp->unp_core_lock); /* * If we're still running on the network, stop and wait for all @@ -1720,9 +1710,7 @@ usbnet_activate(device_t self, devact_t act) case DVACT_DEACTIVATE: if_deactivate(ifp); - mutex_enter(&unp->unp_core_lock); atomic_store_relaxed(&unp->unp_dying, true); - mutex_exit(&unp->unp_core_lock); mutex_enter(&unp->unp_rxlock); mutex_enter(&unp->unp_txlock); From a67b5b0afa97d189759cf9bbe809aab9e8c29efd Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 11:36:01 +0000 Subject: [PATCH 34/77] usbnet drivers: Stop timeout loops early if device is detaching. --- sys/dev/usb/if_aue.c | 6 ++++++ sys/dev/usb/if_mos.c | 4 ++++ sys/dev/usb/if_mue.c | 2 ++ sys/dev/usb/if_smsc.c | 2 ++ sys/dev/usb/if_udav.c | 2 ++ sys/dev/usb/if_ure.c | 10 ++++++++++ sys/dev/usb/if_url.c | 2 ++ 7 files changed, 28 insertions(+) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index b72eff0349c4..b4d0dc36b7b8 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -483,6 +483,8 @@ aue_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_READ); for (i = 0; i < AUE_TIMEOUT; i++) { + if (usbnet_isdying(un)) + return ENXIO; if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE) break; } @@ -524,6 +526,8 @@ aue_uno_mii_write_reg(struct usbnet *un, int phy, int reg, uint16_t val) aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_WRITE); for (i = 0; i < AUE_TIMEOUT; i++) { + if (usbnet_isdying(un)) + return ENXIO; if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE) break; } @@ -680,6 +684,8 @@ aue_reset(struct aue_softc *sc) AUE_SETBIT(sc, AUE_CTL1, AUE_CTL1_RESETMAC); for (i = 0; i < AUE_TIMEOUT; i++) { + if (usbnet_isdying(un)) + return; if (!(aue_csr_read_1(sc, AUE_CTL1) & AUE_CTL1_RESETMAC)) break; } diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index 987bb0484710..e76c9f11893a 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -364,6 +364,8 @@ mos_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) MOS_PHYSTS_PENDING); for (i = 0; i < MOS_TIMEOUT; i++) { + if (usbnet_isdying(un)) + return ENXIO; if (mos_reg_read_1(un, MOS_PHY_STS) & MOS_PHYSTS_READY) break; } @@ -396,6 +398,8 @@ mos_uno_mii_write_reg(struct usbnet *un, int phy, int reg, uint16_t val) MOS_PHYSTS_PENDING); for (i = 0; i < MOS_TIMEOUT; i++) { + if (usbnet_isdying(un)) + return ENXIO; if (mos_reg_read_1(un, MOS_PHY_STS) & MOS_PHYSTS_READY) break; } diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index 81534e865688..034bacc1f587 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -200,6 +200,8 @@ mue_wait_for_bits(struct usbnet *un, uint32_t reg, int ntries; for (ntries = 0; ntries < 1000; ntries++) { + if (usbnet_isdying(un)) + return 1; val = mue_csr_read(un, reg); if ((val & set) || !(val & clear)) return 0; diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 4361532efc39..de6e4395be5b 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -264,6 +264,8 @@ smsc_wait_for_bits(struct usbnet *un, uint32_t reg, uint32_t bits) int err, i; for (i = 0; i < 100; i++) { + if (usbnet_isdying(un)) + return ENXIO; if ((err = smsc_readreg(un, reg, &val)) != 0) return err; if (!(val & bits)) diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index e22e1f305876..13e5971a4bd6 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -568,6 +568,8 @@ udav_chip_init(struct usbnet *un) UDAV_SETBIT(un, UDAV_NCR, UDAV_NCR_RST); for (int i = 0; i < UDAV_TX_TIMEOUT; i++) { + if (usbnet_isdying(un)) + return; if (!(udav_csr_read1(un, UDAV_NCR) & UDAV_NCR_RST)) break; delay(10); /* XXX */ diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index db75961fc88e..6ad61447dc3a 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -396,6 +396,8 @@ ure_reset(struct usbnet *un) ure_write_1(un, URE_PLA_CR, URE_MCU_TYPE_PLA, URE_CR_RST); for (i = 0; i < URE_TIMEOUT; i++) { + if (usbnet_isdying(un)) + return; if (!(ure_read_1(un, URE_PLA_CR, URE_MCU_TYPE_PLA) & URE_CR_RST)) break; @@ -541,6 +543,8 @@ ure_rtl8153_init(struct usbnet *un) URE_MCU_TYPE_USB | URE_BYTE_EN_SIX_BYTES, u1u2, sizeof(u1u2)); for (i = 0; i < URE_TIMEOUT; i++) { + if (usbnet_isdying(un)) + return; if (ure_read_2(un, URE_PLA_BOOT_CTRL, URE_MCU_TYPE_PLA) & URE_AUTOLOAD_DONE) break; @@ -550,6 +554,8 @@ ure_rtl8153_init(struct usbnet *un) URE_PRINTF(un, "timeout waiting for chip autoload\n"); for (i = 0; i < URE_TIMEOUT; i++) { + if (usbnet_isdying(un)) + return; val = ure_ocp_reg_read(un, URE_OCP_PHY_STATUS) & URE_PHY_STAT_MASK; if (val == URE_PHY_STAT_LAN_ON || val == URE_PHY_STAT_PWRDN) @@ -748,6 +754,8 @@ ure_init_fifo(struct usbnet *un) ure_read_2(un, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA) & ~URE_MCU_BORW_EN); for (i = 0; i < URE_TIMEOUT; i++) { + if (usbnet_isdying(un)) + return; if (ure_read_1(un, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA) & URE_LINK_LIST_READY) break; @@ -759,6 +767,8 @@ ure_init_fifo(struct usbnet *un) ure_read_2(un, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA) | URE_RE_INIT_LL); for (i = 0; i < URE_TIMEOUT; i++) { + if (usbnet_isdying(un)) + return; if (ure_read_1(un, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA) & URE_LINK_LIST_READY) break; diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index af766fcd455d..28674302ab26 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -428,6 +428,8 @@ url_reset(struct usbnet *un) URL_SETBIT(un, URL_CR, URL_CR_SOFT_RST); for (i = 0; i < URL_TX_TIMEOUT; i++) { + if (usbnet_isdying(un)) + return; if (!(url_csr_read_1(un, URL_CR) & URL_CR_SOFT_RST)) break; delay(10); /* XXX */ From 527c87cbb11eea2176a1b8ef0f36b7514d6ef4dd Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 13:12:07 +0000 Subject: [PATCH 35/77] usbnet: Split multicast filter reprogramming into separate operation. --- sys/dev/usb/if_aue.c | 31 +++++++++++++------------------ sys/dev/usb/if_axe.c | 19 +++++-------------- sys/dev/usb/if_axen.c | 20 ++++++++++++++++---- sys/dev/usb/if_cue.c | 19 +++++-------------- sys/dev/usb/if_kue.c | 19 +++++-------------- sys/dev/usb/if_mos.c | 19 +++++-------------- sys/dev/usb/if_mue.c | 20 ++++++++++++++++---- sys/dev/usb/if_smsc.c | 20 ++++++++++++++++---- sys/dev/usb/if_udav.c | 19 +++++-------------- sys/dev/usb/if_ure.c | 19 +++++-------------- sys/dev/usb/if_url.c | 19 +++++-------------- sys/dev/usb/usbnet.c | 24 +++++++++--------------- sys/dev/usb/usbnet.h | 14 ++++++++++---- 13 files changed, 115 insertions(+), 147 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index b4d0dc36b7b8..c47324b59848 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -240,7 +240,7 @@ CFATTACH_DECL_NEW(aue, sizeof(struct aue_softc), aue_match, aue_attach, static void aue_reset_pegasus_II(struct aue_softc *); static void aue_uno_stop(struct ifnet *, int); -static int aue_uno_ioctl(struct ifnet *, u_long, void *); +static void aue_uno_mcast(struct ifnet *); static int aue_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *); static int aue_uno_mii_write_reg(struct usbnet *, int, int, uint16_t); static void aue_uno_mii_statchg(struct ifnet *); @@ -252,7 +252,7 @@ static void aue_uno_intr(struct usbnet *, usbd_status); static const struct usbnet_ops aue_ops = { .uno_stop = aue_uno_stop, - .uno_ioctl = aue_uno_ioctl, + .uno_mcast = aue_uno_mcast, .uno_read_reg = aue_uno_mii_read_reg, .uno_write_reg = aue_uno_mii_write_reg, .uno_statchg = aue_uno_mii_statchg, @@ -1013,28 +1013,23 @@ aue_uno_init(struct ifnet *ifp) return rv; } -static int -aue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) +static void +aue_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; AUEHIST_FUNC(); - AUEHIST_CALLARGSN(5, "aue%jd: enter cmd %#jx data %#jx", + AUEHIST_CALLARGSN(5, "aue%jd: enter", device_unit(((struct usbnet *)(ifp->if_softc))->un_dev), - cmd, (uintptr_t)data, 0); - - switch (cmd) { - case SIOCADDMULTI: - case SIOCDELMULTI: - usbnet_lock_core(un); - aue_uno_init(ifp); - usbnet_unlock_core(un); - break; - default: - break; - } + 0, 0, 0); - return 0; + /* + * XXX I feel like this is pretty heavy-handed! Maybe we could + * make do with aue_setiff_locked instead? + */ + usbnet_lock_core(un); + aue_uno_init(ifp); + usbnet_unlock_core(un); } static void diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index 78a4a6546f70..20ca7b276760 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -259,7 +259,7 @@ CFATTACH_DECL_NEW(axe, sizeof(struct axe_softc), axe_match, axe_attach, usbnet_detach, usbnet_activate); static void axe_uno_stop(struct ifnet *, int); -static int axe_uno_ioctl(struct ifnet *, u_long, void *); +static void axe_uno_mcast(struct ifnet *); static int axe_uno_init(struct ifnet *); static int axe_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *); static int axe_uno_mii_write_reg(struct usbnet *, int, int, uint16_t); @@ -276,7 +276,7 @@ static void axe_ax88772b_init(struct axe_softc *); static const struct usbnet_ops axe_ops = { .uno_stop = axe_uno_stop, - .uno_ioctl = axe_uno_ioctl, + .uno_mcast = axe_uno_mcast, .uno_read_reg = axe_uno_mii_read_reg, .uno_write_reg = axe_uno_mii_write_reg, .uno_statchg = axe_uno_mii_statchg, @@ -1324,27 +1324,18 @@ axe_uno_init(struct ifnet *ifp) return ret; } -static int -axe_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) +static void +axe_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); usbnet_busy(un); - switch (cmd) { - case SIOCADDMULTI: - case SIOCDELMULTI: - axe_rcvfilt_locked(un); - break; - default: - break; - } + axe_rcvfilt_locked(un); usbnet_unbusy(un); usbnet_unlock_core(un); - - return 0; } static void diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index 7d90fa1259f9..3c12ad38c0a7 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -80,6 +80,7 @@ static void axen_ax88179_init(struct usbnet *); static void axen_uno_stop(struct ifnet *, int); static int axen_uno_ioctl(struct ifnet *, u_long, void *); +static void axen_uno_mcast(struct ifnet *); static int axen_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *); static int axen_uno_mii_write_reg(struct usbnet *, int, int, uint16_t); static void axen_uno_mii_statchg(struct ifnet *); @@ -92,6 +93,7 @@ static int axen_uno_init(struct ifnet *); static const struct usbnet_ops axen_ops = { .uno_stop = axen_uno_stop, .uno_ioctl = axen_uno_ioctl, + .uno_mcast = axen_uno_mcast, .uno_read_reg = axen_uno_mii_read_reg, .uno_write_reg = axen_uno_mii_write_reg, .uno_statchg = axen_uno_mii_statchg, @@ -559,10 +561,6 @@ axen_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) usbnet_busy(un); switch (cmd) { - case SIOCADDMULTI: - case SIOCDELMULTI: - axen_setiff_locked(un); - break; case SIOCSIFCAP: axen_setoe_locked(un); break; @@ -576,6 +574,20 @@ axen_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) return 0; } +static void +axen_uno_mcast(struct ifnet *ifp) +{ + struct usbnet * const un = ifp->if_softc; + + usbnet_lock_core(un); + usbnet_busy(un); + + axen_setiff_locked(un); + + usbnet_unbusy(un); + usbnet_unlock_core(un); +} + static int axen_match(device_t parent, cfdata_t match, void *aux) { diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index 191f31eb9eca..54a6c8535e12 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -141,14 +141,14 @@ CFATTACH_DECL_NEW(cue, sizeof(struct cue_softc), cue_match, cue_attach, static unsigned cue_uno_tx_prepare(struct usbnet *, struct mbuf *, struct usbnet_chain *); static void cue_uno_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); -static int cue_uno_ioctl(struct ifnet *, u_long, void *); +static void cue_uno_mcast(struct ifnet *); static void cue_uno_stop(struct ifnet *, int); static int cue_uno_init(struct ifnet *); static void cue_uno_tick(struct usbnet *); static const struct usbnet_ops cue_ops = { .uno_stop = cue_uno_stop, - .uno_ioctl = cue_uno_ioctl, + .uno_mcast = cue_uno_mcast, .uno_tx_prepare = cue_uno_tx_prepare, .uno_rx_loop = cue_uno_rx_loop, .uno_init = cue_uno_init, @@ -680,27 +680,18 @@ cue_uno_init(struct ifnet *ifp) return rv; } -static int -cue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) +static void +cue_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); usbnet_busy(un); - switch (cmd) { - case SIOCADDMULTI: - case SIOCDELMULTI: - cue_setiff_locked(un); - break; - default: - break; - } + cue_setiff_locked(un); usbnet_unbusy(un); usbnet_unlock_core(un); - - return 0; } /* Stop and reset the adapter. */ diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index 6d8af3cd0735..6c2f417e74df 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -174,11 +174,11 @@ CFATTACH_DECL_NEW(kue, sizeof(struct kue_softc), kue_match, kue_attach, static void kue_uno_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); static unsigned kue_uno_tx_prepare(struct usbnet *, struct mbuf *, struct usbnet_chain *); -static int kue_uno_ioctl(struct ifnet *, u_long, void *); +static void kue_uno_mcast(struct ifnet *); static int kue_uno_init(struct ifnet *); static const struct usbnet_ops kue_ops = { - .uno_ioctl = kue_uno_ioctl, + .uno_mcast = kue_uno_mcast, .uno_tx_prepare = kue_uno_tx_prepare, .uno_rx_loop = kue_uno_rx_loop, .uno_init = kue_uno_init, @@ -640,27 +640,18 @@ kue_uno_init(struct ifnet *ifp) return rv; } -static int -kue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) +static void +kue_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); usbnet_busy(un); - switch (cmd) { - case SIOCADDMULTI: - case SIOCDELMULTI: - kue_setiff_locked(un); - break; - default: - break; - } + kue_setiff_locked(un); usbnet_unbusy(un); usbnet_unlock_core(un); - - return 0; } #ifdef _MODULE diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index e76c9f11893a..26d048b20310 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -145,7 +145,7 @@ CFATTACH_DECL_NEW(mos, sizeof(struct usbnet), static void mos_uno_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); static unsigned mos_uno_tx_prepare(struct usbnet *, struct mbuf *, struct usbnet_chain *); -static int mos_uno_ioctl(struct ifnet *, u_long, void *); +static void mos_uno_mcast(struct ifnet *); static int mos_uno_init(struct ifnet *); static void mos_chip_init(struct usbnet *); static void mos_uno_stop(struct ifnet *ifp, int disable); @@ -164,7 +164,7 @@ static int mos_write_mcast(struct usbnet *, uint8_t *); static const struct usbnet_ops mos_ops = { .uno_stop = mos_uno_stop, - .uno_ioctl = mos_uno_ioctl, + .uno_mcast = mos_uno_mcast, .uno_read_reg = mos_uno_mii_read_reg, .uno_write_reg = mos_uno_mii_write_reg, .uno_statchg = mos_uno_mii_statchg, @@ -771,27 +771,18 @@ mos_uno_init(struct ifnet *ifp) return ret; } -static int -mos_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) +static void +mos_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); usbnet_busy(un); - switch (cmd) { - case SIOCADDMULTI: - case SIOCDELMULTI: - mos_rcvfilt_locked(un); - break; - default: - break; - } + mos_rcvfilt_locked(un); usbnet_unbusy(un); usbnet_unlock_core(un); - - return 0; } void diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index 034bacc1f587..fe14f4422d8f 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -99,6 +99,7 @@ static void mue_reset(struct usbnet *); static void mue_uno_stop(struct ifnet *, int); static int mue_uno_ioctl(struct ifnet *, u_long, void *); +static void mue_uno_mcast(struct ifnet *); static int mue_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *); static int mue_uno_mii_write_reg(struct usbnet *, int, int, uint16_t); static void mue_uno_mii_statchg(struct ifnet *); @@ -111,6 +112,7 @@ static int mue_uno_init(struct ifnet *); static const struct usbnet_ops mue_ops = { .uno_stop = mue_uno_stop, .uno_ioctl = mue_uno_ioctl, + .uno_mcast = mue_uno_mcast, .uno_read_reg = mue_uno_mii_read_reg, .uno_write_reg = mue_uno_mii_write_reg, .uno_statchg = mue_uno_mii_statchg, @@ -1273,10 +1275,6 @@ mue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) usbnet_busy(un); switch (cmd) { - case SIOCADDMULTI: - case SIOCDELMULTI: - mue_setiff_locked(un); - break; case SIOCSIFCAP: mue_sethwcsum_locked(un); break; @@ -1293,6 +1291,20 @@ mue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) return 0; } +static void +mue_uno_mcast(struct ifnet *ifp) +{ + struct usbnet * const un = ifp->if_softc; + + usbnet_lock_core(un); + usbnet_busy(un); + + mue_setiff_locked(un); + + usbnet_unbusy(un); + usbnet_unlock_core(un); +} + static void mue_reset(struct usbnet *un) { diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index de6e4395be5b..d749af747e09 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -187,6 +187,7 @@ static int smsc_uno_miibus_readreg(struct usbnet *, int, int, uint16_t *); static int smsc_uno_miibus_writereg(struct usbnet *, int, int, uint16_t); static int smsc_uno_ioctl(struct ifnet *, u_long, void *); +static void smsc_uno_mcast(struct ifnet *); static unsigned smsc_uno_tx_prepare(struct usbnet *, struct mbuf *, struct usbnet_chain *); static void smsc_uno_rx_loop(struct usbnet *, struct usbnet_chain *, @@ -195,6 +196,7 @@ static void smsc_uno_rx_loop(struct usbnet *, struct usbnet_chain *, static const struct usbnet_ops smsc_ops = { .uno_stop = smsc_uno_stop, .uno_ioctl = smsc_uno_ioctl, + .uno_mcast = smsc_uno_mcast, .uno_read_reg = smsc_uno_miibus_readreg, .uno_write_reg = smsc_uno_miibus_writereg, .uno_statchg = smsc_uno_miibus_statchg, @@ -757,10 +759,6 @@ smsc_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) usbnet_busy(un); switch (cmd) { - case SIOCADDMULTI: - case SIOCDELMULTI: - smsc_setiff_locked(un); - break; case SIOCSIFCAP: smsc_setoe_locked(un); break; @@ -774,6 +772,20 @@ smsc_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) return 0; } +static void +smsc_uno_mcast(struct ifnet *ifp) +{ + struct usbnet * const un = ifp->if_softc; + + usbnet_lock_core(un); + usbnet_busy(un); + + smsc_setiff_locked(un); + + usbnet_unbusy(un); + usbnet_unlock_core(un); +} + static int smsc_match(device_t parent, cfdata_t match, void *aux) { diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index 13e5971a4bd6..45f68f89eb32 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -69,7 +69,7 @@ static unsigned udav_uno_tx_prepare(struct usbnet *, struct mbuf *, struct usbnet_chain *); static void udav_uno_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); static void udav_uno_stop(struct ifnet *, int); -static int udav_uno_ioctl(struct ifnet *, u_long, void *); +static void udav_uno_mcast(struct ifnet *); static int udav_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *); static int udav_uno_mii_write_reg(struct usbnet *, int, int, uint16_t); static void udav_uno_mii_statchg(struct ifnet *); @@ -132,7 +132,7 @@ static const struct udav_type { static const struct usbnet_ops udav_ops = { .uno_stop = udav_uno_stop, - .uno_ioctl = udav_uno_ioctl, + .uno_mcast = udav_uno_mcast, .uno_read_reg = udav_uno_mii_read_reg, .uno_write_reg = udav_uno_mii_write_reg, .uno_statchg = udav_uno_mii_statchg, @@ -718,27 +718,18 @@ udav_uno_rx_loop(struct usbnet *un, struct usbnet_chain *c, uint32_t total_len) usbnet_enqueue(un, buf, pkt_len, 0, 0, 0); } -static int -udav_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) +static void +udav_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); usbnet_busy(un); - switch (cmd) { - case SIOCADDMULTI: - case SIOCDELMULTI: - udav_setiff_locked(un); - break; - default: - break; - } + udav_setiff_locked(un); usbnet_unbusy(un); usbnet_unlock_core(un); - - return 0; } /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index 6ad61447dc3a..480bc05e1e6d 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -86,7 +86,7 @@ static void ure_disable_teredo(struct usbnet *); static void ure_init_fifo(struct usbnet *); static void ure_uno_stop(struct ifnet *, int); -static int ure_uno_ioctl(struct ifnet *, u_long, void *); +static void ure_uno_mcast(struct ifnet *); static int ure_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *); static int ure_uno_mii_write_reg(struct usbnet *, int, int, uint16_t); static void ure_uno_miibus_statchg(struct ifnet *); @@ -104,7 +104,7 @@ CFATTACH_DECL_NEW(ure, sizeof(struct usbnet), ure_match, ure_attach, static const struct usbnet_ops ure_ops = { .uno_stop = ure_uno_stop, - .uno_ioctl = ure_uno_ioctl, + .uno_mcast = ure_uno_mcast, .uno_read_reg = ure_uno_mii_read_reg, .uno_write_reg = ure_uno_mii_write_reg, .uno_statchg = ure_uno_miibus_statchg, @@ -802,27 +802,18 @@ ure_init_fifo(struct usbnet *un) URE_TXFIFO_THR_NORMAL); } -static int -ure_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) +static void +ure_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); usbnet_busy(un); - switch (cmd) { - case SIOCADDMULTI: - case SIOCDELMULTI: - ure_rcvfilt_locked(un); - break; - default: - break; - } + ure_rcvfilt_locked(un); usbnet_unbusy(un); usbnet_unlock_core(un); - - return 0; } static int diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index 28674302ab26..907d759f9ad8 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -77,7 +77,7 @@ static unsigned url_uno_tx_prepare(struct usbnet *, struct mbuf *, static void url_uno_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); static int url_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *); static int url_uno_mii_write_reg(struct usbnet *, int, int, uint16_t); -static int url_uno_ioctl(struct ifnet *, u_long, void *); +static void url_uno_mcast(struct ifnet *); static void url_uno_stop(struct ifnet *, int); static void url_uno_mii_statchg(struct ifnet *); static int url_uno_init(struct ifnet *); @@ -93,7 +93,7 @@ static int url_mem(struct usbnet *, int, int, void *, int); static const struct usbnet_ops url_ops = { .uno_stop = url_uno_stop, - .uno_ioctl = url_uno_ioctl, + .uno_mcast = url_uno_mcast, .uno_read_reg = url_uno_mii_read_reg, .uno_write_reg = url_uno_mii_write_reg, .uno_statchg = url_uno_mii_statchg, @@ -559,27 +559,18 @@ static void url_intr(void) } #endif -static int -url_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) +static void +url_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); usbnet_busy(un); - switch (cmd) { - case SIOCADDMULTI: - case SIOCDELMULTI: - url_rcvfilt_locked(un); - break; - default: - break; - } + url_rcvfilt_locked(un); usbnet_unbusy(un); usbnet_unlock_core(un); - - return 0; } /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 4ea0859904b9..80911908fa66 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -162,13 +162,9 @@ static int uno_ioctl(struct usbnet *un, struct ifnet *ifp, u_long cmd, void *data) { - switch (cmd) { - case SIOCADDMULTI: - case SIOCDELMULTI: - break; - default: - KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); - } + KASSERTMSG(cmd != SIOCADDMULTI, "%s", ifp->if_xname); + KASSERTMSG(cmd != SIOCDELMULTI, "%s", ifp->if_xname); + KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); if (un->un_ops->uno_ioctl) return (*un->un_ops->uno_ioctl)(ifp, cmd, data); @@ -1076,7 +1072,6 @@ usbnet_mcast_task(void *arg) USBNETHIST_FUNC(); struct usbnet * const un = arg; struct ifnet * const ifp = usbnet_ifp(un); - struct ifreq ifr; USBNETHIST_CALLARGSN(10, "%jd: enter", un->un_pri->unp_number, 0, 0, 0); @@ -1094,16 +1089,15 @@ usbnet_mcast_task(void *arg) return; /* - * Pass a bogus ifr with SIOCDELMULTI -- the goal is to just - * notify the driver to reprogram any hardware multicast - * filter, according to what's already stored in the ethercom. - * None of the drivers actually examine this argument, so it - * doesn't change the ABI as far as they can tell. + * If the hardware is running, ask the driver to reprogram the + * multicast filter. If the hardware is not running, the + * driver is responsible for programming the multicast filter + * as part of its uno_init routine to bring the hardware up. */ IFNET_LOCK(ifp); if (ifp->if_flags & IFF_RUNNING) { - memset(&ifr, 0, sizeof(ifr)); - (void)uno_ioctl(un, ifp, SIOCDELMULTI, &ifr); + if (un->un_ops->uno_mcast) + (*un->un_ops->uno_mcast)(ifp); } IFNET_UNLOCK(ifp); } diff --git a/sys/dev/usb/usbnet.h b/sys/dev/usb/usbnet.h index 1faa822887c5..dc19d49fa15c 100644 --- a/sys/dev/usb/usbnet.h +++ b/sys/dev/usb/usbnet.h @@ -131,6 +131,8 @@ enum usbnet_ep { typedef void (*usbnet_stop_cb)(struct ifnet *, int); /* Interface ioctl callback. */ typedef int (*usbnet_ioctl_cb)(struct ifnet *, u_long, void *); +/* Reprogram multicast filters callback. */ +typedef void (*usbnet_mcast_cb)(struct ifnet *); /* Initialise device callback. */ typedef int (*usbnet_init_cb)(struct ifnet *); @@ -170,16 +172,20 @@ typedef void (*usbnet_intr_cb)(struct usbnet *, usbd_status); * Note that when CORE_LOCK is held, IFNET_LOCK may or may not also * be held. * - * Note that the IFNET_LOCK **may not be held** for some ioctl - * operations (add/delete multicast addresses, for example). + * Note that the IFNET_LOCK **may not be held** for the ioctl commands + * SIOCADDMULTI/SIOCDELMULTI. These commands are only passed + * explicitly to uno_override_ioctl; for all other devices, they are + * handled inside usbnet by scheduling a task to asynchronously call + * uno_mcast with IFNET_LOCK held. * * Busy reference counts are maintained across calls to: uno_stop, * uno_read_reg, uno_write_reg, uno_statchg, and uno_tick. */ struct usbnet_ops { usbnet_stop_cb uno_stop; /* C */ - usbnet_ioctl_cb uno_ioctl; /* I (maybe) */ - usbnet_ioctl_cb uno_override_ioctl; /* I (maybe) */ + usbnet_ioctl_cb uno_ioctl; /* I */ + usbnet_ioctl_cb uno_override_ioctl; /* I (except mcast) */ + usbnet_mcast_cb uno_mcast; /* I */ usbnet_init_cb uno_init; /* I */ usbnet_mii_read_reg_cb uno_read_reg; /* C */ usbnet_mii_write_reg_cb uno_write_reg; /* C */ From d8282aa108a179ea3b66c15994dc1b1093947c29 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 13:32:54 +0000 Subject: [PATCH 36/77] usbnet drivers: No need for usbnet_busy in uno_init. This callback always runs with the IFNET_LOCK held, and the interface cannot be detached until the IFNET_LOCK is released, so there is no need to hang onto a reference count here. (None of the usbnet drivers touch the IFNET_LOCK except to verify it is held sometimes.) --- sys/dev/usb/if_aue.c | 3 --- sys/dev/usb/if_axe.c | 4 ---- sys/dev/usb/if_axen.c | 4 ---- sys/dev/usb/if_cue.c | 3 --- sys/dev/usb/if_kue.c | 3 --- sys/dev/usb/if_mos.c | 4 ---- sys/dev/usb/if_mue.c | 3 --- sys/dev/usb/if_smsc.c | 4 ---- sys/dev/usb/if_udav.c | 5 ----- sys/dev/usb/if_ure.c | 4 ---- sys/dev/usb/if_url.c | 4 ---- 11 files changed, 41 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index c47324b59848..058c8ae923be 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -1003,12 +1003,9 @@ aue_init_locked(struct ifnet *ifp) static int aue_uno_init(struct ifnet *ifp) { - struct usbnet * const un = ifp->if_softc; int rv; - usbnet_busy(un); rv = aue_init_locked(ifp); - usbnet_unbusy(un); return rv; } diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index 20ca7b276760..252f28ef8b14 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -1315,11 +1315,7 @@ axe_init_locked(struct ifnet *ifp) static int axe_uno_init(struct ifnet *ifp) { - struct usbnet * const un = ifp->if_softc; - - usbnet_busy(un); int ret = axe_init_locked(ifp); - usbnet_unbusy(un); return ret; } diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index 3c12ad38c0a7..f8199ca2f1fc 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -945,11 +945,7 @@ axen_init_locked(struct ifnet *ifp) static int axen_uno_init(struct ifnet *ifp) { - struct usbnet * const un = ifp->if_softc; - - usbnet_busy(un); int ret = axen_init_locked(ifp); - usbnet_unbusy(un); return ret; } diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index 54a6c8535e12..6c2db667ba82 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -670,12 +670,9 @@ cue_init_locked(struct ifnet *ifp) static int cue_uno_init(struct ifnet *ifp) { - struct usbnet * const un = ifp->if_softc; int rv; - usbnet_busy(un); rv = cue_init_locked(ifp); - usbnet_unbusy(un); return rv; } diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index 6c2f417e74df..7d2a03e14c8c 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -630,12 +630,9 @@ kue_init_locked(struct ifnet *ifp) static int kue_uno_init(struct ifnet *ifp) { - struct usbnet * const un = ifp->if_softc; int rv; - usbnet_busy(un); rv = kue_init_locked(ifp); - usbnet_unbusy(un); return rv; } diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index 26d048b20310..03601b9e752b 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -762,11 +762,7 @@ mos_init_locked(struct ifnet *ifp) static int mos_uno_init(struct ifnet *ifp) { - struct usbnet * const un = ifp->if_softc; - - usbnet_busy(un); int ret = mos_init_locked(ifp); - usbnet_unbusy(un); return ret; } diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index fe14f4422d8f..e41fe6b6b091 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1256,12 +1256,9 @@ mue_init_locked(struct ifnet *ifp) static int mue_uno_init(struct ifnet *ifp) { - struct usbnet * const un = ifp->if_softc; int rv; - usbnet_busy(un); rv = mue_init_locked(ifp); - usbnet_unbusy(un); return rv; } diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index d749af747e09..718638357b93 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -554,11 +554,7 @@ smsc_reset(struct smsc_softc *sc) static int smsc_uno_init(struct ifnet *ifp) { - struct usbnet * const un = ifp->if_softc; - - usbnet_busy(un); int ret = smsc_init_locked(ifp); - usbnet_unbusy(un); return ret; } diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index 45f68f89eb32..fe70dfb17012 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -486,8 +486,6 @@ udav_uno_init(struct ifnet *ifp) if (ifp->if_flags & IFF_RUNNING) usbnet_stop(un, ifp, 1); - usbnet_busy(un); - memcpy(eaddr, CLLADDR(ifp->if_sadl), sizeof(eaddr)); udav_csr_write(un, UDAV_PAR, eaddr, ETHER_ADDR_LEN); @@ -518,7 +516,6 @@ udav_uno_init(struct ifnet *ifp) rc = 0; if (rc != 0) { - usbnet_unbusy(un); return rc; } @@ -527,8 +524,6 @@ udav_uno_init(struct ifnet *ifp) else rc = usbnet_init_rx_tx(un); - usbnet_unbusy(un); - return rc; } diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index 480bc05e1e6d..669677836f8d 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -456,11 +456,7 @@ ure_init_locked(struct ifnet *ifp) static int ure_uno_init(struct ifnet *ifp) { - struct usbnet * const un = ifp->if_softc; - - usbnet_busy(un); int ret = ure_init_locked(ifp); - usbnet_unbusy(un); return ret; } diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index 907d759f9ad8..b0f48c5249c8 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -406,11 +406,7 @@ url_init_locked(struct ifnet *ifp) static int url_uno_init(struct ifnet *ifp) { - struct usbnet * const un = ifp->if_softc; - - usbnet_busy(un); int ret = url_init_locked(ifp); - usbnet_unbusy(un); return ret; } From 9e37923c818078d9934da6cc9f4c5c3643a2f6bb Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 13:35:32 +0000 Subject: [PATCH 37/77] usbnet drivers: No need for usbnet_busy in uno_mcast. This callback always runs with IFNET_LOCK held, and during a task that usbnet_detach prevents scheduling anew and waits for finishing before completing the detach, so there is no need to hang onto a reference count here. --- sys/dev/usb/if_axe.c | 2 -- sys/dev/usb/if_axen.c | 2 -- sys/dev/usb/if_cue.c | 2 -- sys/dev/usb/if_kue.c | 2 -- sys/dev/usb/if_mos.c | 2 -- sys/dev/usb/if_mue.c | 2 -- sys/dev/usb/if_smsc.c | 2 -- sys/dev/usb/if_udav.c | 2 -- sys/dev/usb/if_ure.c | 2 -- sys/dev/usb/if_url.c | 2 -- 10 files changed, 20 deletions(-) diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index 252f28ef8b14..5f7663e435e0 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -1326,11 +1326,9 @@ axe_uno_mcast(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); - usbnet_busy(un); axe_rcvfilt_locked(un); - usbnet_unbusy(un); usbnet_unlock_core(un); } diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index f8199ca2f1fc..96f17df1b3cc 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -580,11 +580,9 @@ axen_uno_mcast(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); - usbnet_busy(un); axen_setiff_locked(un); - usbnet_unbusy(un); usbnet_unlock_core(un); } diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index 6c2db667ba82..646cef9178b5 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -683,11 +683,9 @@ cue_uno_mcast(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); - usbnet_busy(un); cue_setiff_locked(un); - usbnet_unbusy(un); usbnet_unlock_core(un); } diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index 7d2a03e14c8c..c02f40a77dcf 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -643,11 +643,9 @@ kue_uno_mcast(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); - usbnet_busy(un); kue_setiff_locked(un); - usbnet_unbusy(un); usbnet_unlock_core(un); } diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index 03601b9e752b..1c27bcb6f308 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -773,11 +773,9 @@ mos_uno_mcast(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); - usbnet_busy(un); mos_rcvfilt_locked(un); - usbnet_unbusy(un); usbnet_unlock_core(un); } diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index e41fe6b6b091..663ef0f49c2a 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1294,11 +1294,9 @@ mue_uno_mcast(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); - usbnet_busy(un); mue_setiff_locked(un); - usbnet_unbusy(un); usbnet_unlock_core(un); } diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 718638357b93..4e75cf65a499 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -774,11 +774,9 @@ smsc_uno_mcast(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); - usbnet_busy(un); smsc_setiff_locked(un); - usbnet_unbusy(un); usbnet_unlock_core(un); } diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index fe70dfb17012..f0c23cfea3ae 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -719,11 +719,9 @@ udav_uno_mcast(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); - usbnet_busy(un); udav_setiff_locked(un); - usbnet_unbusy(un); usbnet_unlock_core(un); } diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index 669677836f8d..45b18f48438c 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -804,11 +804,9 @@ ure_uno_mcast(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); - usbnet_busy(un); ure_rcvfilt_locked(un); - usbnet_unbusy(un); usbnet_unlock_core(un); } diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index b0f48c5249c8..cbc125bd08ea 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -561,11 +561,9 @@ url_uno_mcast(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); - usbnet_busy(un); url_rcvfilt_locked(un); - usbnet_unbusy(un); usbnet_unlock_core(un); } From ffa560baad9afd313852d9499b4792f4b839c4b0 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 13:37:56 +0000 Subject: [PATCH 38/77] usbnet drivers: No need for usbnet_busy in uno_ioctl. This callback always runs with the IFNET_LOCK held, and the interface cannot be detached until the IFNET_LOCK is released, so there is no need to hang onto a reference count here. (None of the subnet drivers touch the IFNET_LOCK except to verify it is held sometimes.) --- sys/dev/usb/if_axen.c | 2 -- sys/dev/usb/if_mue.c | 2 -- sys/dev/usb/if_smsc.c | 2 -- 3 files changed, 6 deletions(-) diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index 96f17df1b3cc..44bb96944b7a 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -558,7 +558,6 @@ axen_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); - usbnet_busy(un); switch (cmd) { case SIOCSIFCAP: @@ -568,7 +567,6 @@ axen_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) break; } - usbnet_unbusy(un); usbnet_unlock_core(un); return 0; diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index 663ef0f49c2a..d6ab282aa2d7 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1269,7 +1269,6 @@ mue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); - usbnet_busy(un); switch (cmd) { case SIOCSIFCAP: @@ -1282,7 +1281,6 @@ mue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) break; } - usbnet_unbusy(un); usbnet_unlock_core(un); return 0; diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 4e75cf65a499..d61315fed14d 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -752,7 +752,6 @@ smsc_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) struct usbnet * const un = ifp->if_softc; usbnet_lock_core(un); - usbnet_busy(un); switch (cmd) { case SIOCSIFCAP: @@ -762,7 +761,6 @@ smsc_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) break; } - usbnet_unbusy(un); usbnet_unlock_core(un); return 0; From 6c27ea9313000b9aad1b3360f6261391c3f61500 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 13:39:06 +0000 Subject: [PATCH 39/77] usbnet drivers: No need for usbnet_busy during attach. usbnet_detach cannot run until the attach routine has finished (unless a driver goes out of its way to tie its shoelaces together and explicitly call it during the attach routine, which none of them do), so there is no need to hang onto a reference count that we release before attach returns. --- sys/dev/usb/if_axe.c | 4 ---- sys/dev/usb/if_axen.c | 6 ------ sys/dev/usb/if_smsc.c | 2 -- sys/dev/usb/if_udav.c | 2 -- sys/dev/usb/if_url.c | 2 -- 5 files changed, 16 deletions(-) diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index 5f7663e435e0..5f65f8d53085 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -930,10 +930,8 @@ axe_attach(device_t parent, device_t self, void *aux) /* We need the PHYID for init dance in some cases */ usbnet_lock_core(un); - usbnet_busy(un); if (axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, &sc->axe_phyaddrs)) { aprint_error_dev(self, "failed to read phyaddrs\n"); - usbnet_unbusy(un); usbnet_unlock_core(un); return; } @@ -964,13 +962,11 @@ axe_attach(device_t parent, device_t self, void *aux) } else { if (axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, sc->axe_ipgs)) { aprint_error_dev(self, "failed to read ipg\n"); - usbnet_unbusy(un); usbnet_unlock_core(un); return; } } - usbnet_unbusy(un); usbnet_unlock_core(un); if (!AXE_IS_172(un)) diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index 44bb96944b7a..ae07b34b0daa 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -368,7 +368,6 @@ axen_ax88179_init(struct usbnet *un) uint8_t val; usbnet_lock_core(un); - usbnet_busy(un); /* XXX: ? */ axen_cmd(un, AXEN_CMD_MAC_READ, 1, AXEN_UNK_05, &val); @@ -452,7 +451,6 @@ axen_ax88179_init(struct usbnet *un) default: aprint_error_dev(un->un_dev, "unknown uplink bus:0x%02x\n", val); - usbnet_unbusy(un); usbnet_unlock_core(un); return; } @@ -512,7 +510,6 @@ axen_ax88179_init(struct usbnet *un) usbnet_mii_writereg(un->un_dev, un->un_phyno, 0x1F, 0x0000); #endif - usbnet_unbusy(un); usbnet_unlock_core(un); } @@ -682,14 +679,11 @@ axen_attach(device_t parent, device_t self, void *aux) /* Get station address. */ usbnet_lock_core(un); - usbnet_busy(un); if (axen_get_eaddr(un, &un->un_eaddr)) { - usbnet_unbusy(un); usbnet_unlock_core(un); printf("EEPROM checksum error\n"); return; } - usbnet_unbusy(un); usbnet_unlock_core(un); axen_ax88179_init(un); diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index d61315fed14d..a48336f8b972 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -884,7 +884,6 @@ smsc_attach(device_t parent, device_t self, void *aux) un->un_phyno = 1; usbnet_lock_core(un); - usbnet_busy(un); /* * Attempt to get the mac address, if an EEPROM is not attached this * will just return FF:FF:FF:FF:FF:FF, so in such cases we invent a MAC @@ -912,7 +911,6 @@ smsc_attach(device_t parent, device_t self, void *aux) un->un_eaddr[0] = (uint8_t)((mac_l) & 0xff); } } - usbnet_unbusy(un); usbnet_unlock_core(un); usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index f0c23cfea3ae..77f9bd353c5e 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -240,14 +240,12 @@ udav_attach(device_t parent, device_t self, void *aux) usbnet_attach(un, "udavdet"); usbnet_lock_core(un); - usbnet_busy(un); // /* reset the adapter */ // udav_reset(un); /* Get Ethernet Address */ err = udav_csr_read(un, UDAV_PAR, un->un_eaddr, ETHER_ADDR_LEN); - usbnet_unbusy(un); usbnet_unlock_core(un); if (err) { aprint_error_dev(self, "read MAC address failed\n"); diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index cbc125bd08ea..82f1772f180f 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -244,7 +244,6 @@ url_attach(device_t parent, device_t self, void *aux) usbnet_attach(un, "urldet"); usbnet_lock_core(un); - usbnet_busy(un); /* reset the adapter */ url_reset(un); @@ -252,7 +251,6 @@ url_attach(device_t parent, device_t self, void *aux) /* Get Ethernet Address */ err = url_mem(un, URL_CMD_READMEM, URL_IDR0, (void *)un->un_eaddr, ETHER_ADDR_LEN); - usbnet_unbusy(un); usbnet_unlock_core(un); if (err) { aprint_error_dev(self, "read MAC address failed\n"); From 74f5690765e0f7ced7ea58d4d8afc884e97168b5 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 13:46:11 +0000 Subject: [PATCH 40/77] usbnet: No need for usbnet_busy in usbnet_init_rx_tx or usbnet_stop. These run with IFNET_LOCK held, and the interface cannot be detached until the IFNET_LOCK is released, so there is no need to hang onto a reference count here. --- sys/dev/usb/usbnet.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 80911908fa66..64221164a70c 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -837,8 +837,6 @@ usbnet_init_rx_tx(struct usbnet * const un) return EIO; } - usbnet_busy(un); - /* Open RX and TX pipes. */ err = usbnet_ep_open_pipes(un); if (err) { @@ -879,7 +877,6 @@ out: usbnet_tx_list_fini(un); usbnet_ep_close_pipes(un); } - usbnet_unbusy(un); usbnet_isowned_core(un); @@ -1126,8 +1123,6 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) "%s", ifp->if_xname); usbnet_isowned_core(un); - usbnet_busy(un); - /* * Prevent new activity (rescheduling ticks, xfers, &c.) and * clear the watchdog timer. @@ -1176,8 +1171,6 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) KASSERTMSG(!unp->unp_ifp_attached || IFNET_LOCKED(ifp), "%s", ifp->if_xname); ifp->if_flags &= ~IFF_RUNNING; - - usbnet_unbusy(un); } static void From 7df0119794aebdfce7a414e7c4b334dafacd6fbe Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 13:48:26 +0000 Subject: [PATCH 41/77] usbnet: No need for usbnet_busy in mii callbacks. After mii_detach, these have all completed and no new ones can be made, and detach doesn't start destroying anything until after mii_detach has returned, so there is no need to hang onto a reference count here. --- sys/dev/usb/usbnet.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 64221164a70c..03c33cda6caf 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -920,10 +920,7 @@ usbnet_mii_readreg(device_t dev, int phy, int reg, uint16_t *val) return EIO; } - usbnet_busy(un); err = uno_read_reg(un, phy, reg, val); - usbnet_unbusy(un); - if (err) { USBNETHIST_CALLARGS("%jd: read PHY failed: %jd", un->un_pri->unp_number, err, 0, 0); @@ -947,10 +944,7 @@ usbnet_mii_writereg(device_t dev, int phy, int reg, uint16_t val) return EIO; } - usbnet_busy(un); err = uno_write_reg(un, phy, reg, val); - usbnet_unbusy(un); - if (err) { USBNETHIST_CALLARGS("%jd: write PHY failed: %jd", un->un_pri->unp_number, err, 0, 0); @@ -969,9 +963,7 @@ usbnet_mii_statchg(struct ifnet *ifp) /* MII layer ensures core_lock is held. */ usbnet_isowned_core(un); - usbnet_busy(un); uno_mii_statchg(un, ifp); - usbnet_unbusy(un); } static int From d594837ffa1602b88b5c86ff56d981754d2c8c1a Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 13:51:35 +0000 Subject: [PATCH 42/77] usbnet: usbnet_busy is no longer referenced; release it! --- sys/dev/usb/usbnet.c | 38 -------------------------------------- sys/dev/usb/usbnet.h | 6 ------ 2 files changed, 44 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 03c33cda6caf..7b5cc90fe0e9 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -56,7 +56,6 @@ struct usbnet_private { * and the MII / media data. * - unp_rxlock protects the rx path and its data * - unp_txlock protects the tx path and its data - * - unp_detachcv handles detach vs open references * * the lock ordering is: * ifnet lock -> unp_core_lock -> unp_rxlock -> unp_txlock @@ -66,7 +65,6 @@ struct usbnet_private { kmutex_t unp_core_lock; kmutex_t unp_rxlock; kmutex_t unp_txlock; - kcondvar_t unp_detachcv; struct usbnet_cdata unp_cdata; @@ -83,7 +81,6 @@ struct usbnet_private { bool unp_ifp_attached; bool unp_link; - int unp_refcnt; int unp_timer; unsigned short unp_if_flags; unsigned unp_number; @@ -883,27 +880,6 @@ out: return error; } -void -usbnet_busy(struct usbnet *un) -{ - struct usbnet_private * const unp = un->un_pri; - - usbnet_isowned_core(un); - - unp->unp_refcnt++; -} - -void -usbnet_unbusy(struct usbnet *un) -{ - struct usbnet_private * const unp = un->un_pri; - - usbnet_isowned_core(un); - - if (--unp->unp_refcnt < 0) - cv_broadcast(&unp->unp_detachcv); -} - /* MII management. */ int @@ -1443,7 +1419,6 @@ usbnet_attach(struct usbnet *un, mutex_init(&unp->unp_txlock, MUTEX_DEFAULT, IPL_SOFTUSB); mutex_init(&unp->unp_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB); mutex_init(&unp->unp_core_lock, MUTEX_DEFAULT, IPL_NONE); - cv_init(&unp->unp_detachcv, detname); rnd_attach_source(&unp->unp_rndsrc, device_xname(un->un_dev), RND_TYPE_NET, RND_FLAG_DEFAULT); @@ -1636,24 +1611,11 @@ usbnet_detach(device_t self, int flags) usb_rem_task_wait(un->un_udev, &unp->unp_mcasttask, USB_TASKQ_DRIVER, NULL); - mutex_enter(&unp->unp_core_lock); - unp->unp_refcnt--; - if (unp->unp_refcnt >= 0) { - aprint_error_dev(un->un_dev, "%d stragglers\n", - unp->unp_refcnt + 1); - } - while (unp->unp_refcnt >= 0) { - /* Wait for processes to go away */ - cv_wait(&unp->unp_detachcv, &unp->unp_core_lock); - } - mutex_exit(&unp->unp_core_lock); - usbnet_rx_list_free(un); usbnet_tx_list_free(un); rnd_detach_source(&unp->unp_rndsrc); - cv_destroy(&unp->unp_detachcv); mutex_destroy(&unp->unp_core_lock); mutex_destroy(&unp->unp_rxlock); mutex_destroy(&unp->unp_txlock); diff --git a/sys/dev/usb/usbnet.h b/sys/dev/usb/usbnet.h index dc19d49fa15c..4524ee45f049 100644 --- a/sys/dev/usb/usbnet.h +++ b/sys/dev/usb/usbnet.h @@ -177,9 +177,6 @@ typedef void (*usbnet_intr_cb)(struct usbnet *, usbd_status); * explicitly to uno_override_ioctl; for all other devices, they are * handled inside usbnet by scheduling a task to asynchronously call * uno_mcast with IFNET_LOCK held. - * - * Busy reference counts are maintained across calls to: uno_stop, - * uno_read_reg, uno_write_reg, uno_statchg, and uno_tick. */ struct usbnet_ops { usbnet_stop_cb uno_stop; /* C */ @@ -314,9 +311,6 @@ usbnet_isowned_core(struct usbnet *un) KASSERT(mutex_owned(usbnet_mutex_core(un))); } -void usbnet_busy(struct usbnet *); -void usbnet_unbusy(struct usbnet *); - void usbnet_lock_rx(struct usbnet *); void usbnet_unlock_rx(struct usbnet *); kmutex_t *usbnet_mutex_rx(struct usbnet *); From 5354d3d7b67ef66be1d7f35b707bb69f6041ebb7 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 14:02:30 +0000 Subject: [PATCH 43/77] usbnet: Make the tx/rx locks private to usbnet.c. Suffice it for the drivers to know that uno_tx_prepare and uno_rx_loop have exclusive access to the chain, and, for tx, exclusive access to the mbuf. --- sys/dev/usb/if_axe.c | 2 -- sys/dev/usb/if_cdce.c | 2 -- sys/dev/usb/usbnet.c | 41 ++++++++++------------------------------- sys/dev/usb/usbnet.h | 18 ------------------ 4 files changed, 10 insertions(+), 53 deletions(-) diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index 5f65f8d53085..ea22523cc651 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -1136,8 +1136,6 @@ axe_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) size_t hdr_len = 0, tlr_len = 0; int length, boundary; - usbnet_isowned_tx(un); - if (!AXE_IS_172(un)) { /* * Copy the mbuf data into a contiguous buffer, leaving two diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c index 4785d9a4cc9e..c7ee6bef2792 100644 --- a/sys/dev/usb/if_cdce.c +++ b/sys/dev/usb/if_cdce.c @@ -277,8 +277,6 @@ cdce_uno_rx_loop(struct usbnet * un, struct usbnet_chain *c, uint32_t total_len) { struct ifnet *ifp = usbnet_ifp(un); - usbnet_isowned_rx(un); - /* Strip off CRC added by Zaurus, if present */ if (un->un_flags & CDCE_ZAURUS && total_len > 4) total_len -= 4; diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 7b5cc90fe0e9..f780e98cee9f 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -96,6 +96,9 @@ struct usbnet_private { volatile unsigned usbnet_number; +static void usbnet_isowned_rx(struct usbnet *); +static void usbnet_isowned_tx(struct usbnet *); + static int usbnet_modcmd(modcmd_t, void *); #ifdef USB_DEBUG @@ -1323,46 +1326,22 @@ usbnet_unlock_core(struct usbnet *un) mutex_exit(&un->un_pri->unp_core_lock); } -kmutex_t * +kmutex_t* usbnet_mutex_core(struct usbnet *un) { return &un->un_pri->unp_core_lock; } -void -usbnet_lock_rx(struct usbnet *un) -{ - mutex_enter(&un->un_pri->unp_rxlock); -} - -void -usbnet_unlock_rx(struct usbnet *un) -{ - mutex_exit(&un->un_pri->unp_rxlock); -} - -kmutex_t * -usbnet_mutex_rx(struct usbnet *un) -{ - return &un->un_pri->unp_rxlock; -} - -void -usbnet_lock_tx(struct usbnet *un) -{ - mutex_enter(&un->un_pri->unp_txlock); -} - -void -usbnet_unlock_tx(struct usbnet *un) +static void +usbnet_isowned_rx(struct usbnet *un) { - mutex_exit(&un->un_pri->unp_txlock); + KASSERT(mutex_owned(&un->un_pri->unp_rxlock)); } -kmutex_t * -usbnet_mutex_tx(struct usbnet *un) +static void +usbnet_isowned_tx(struct usbnet *un) { - return &un->un_pri->unp_txlock; + KASSERT(mutex_owned(&un->un_pri->unp_txlock)); } /* Autoconf management. */ diff --git a/sys/dev/usb/usbnet.h b/sys/dev/usb/usbnet.h index 4524ee45f049..7ade49a0bd34 100644 --- a/sys/dev/usb/usbnet.h +++ b/sys/dev/usb/usbnet.h @@ -311,24 +311,6 @@ usbnet_isowned_core(struct usbnet *un) KASSERT(mutex_owned(usbnet_mutex_core(un))); } -void usbnet_lock_rx(struct usbnet *); -void usbnet_unlock_rx(struct usbnet *); -kmutex_t *usbnet_mutex_rx(struct usbnet *); -static __inline__ void -usbnet_isowned_rx(struct usbnet *un) -{ - KASSERT(mutex_owned(usbnet_mutex_rx(un))); -} - -void usbnet_lock_tx(struct usbnet *); -void usbnet_unlock_tx(struct usbnet *); -kmutex_t *usbnet_mutex_tx(struct usbnet *); -static __inline__ void -usbnet_isowned_tx(struct usbnet *un) -{ - KASSERT(mutex_owned(usbnet_mutex_tx(un))); -} - /* * Endpoint / rx/tx chain management: * From 2aa385847b40619b1a380e3aa824a676bd47b1a3 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 14:09:23 +0000 Subject: [PATCH 44/77] usbnet: No need for the core lock in usbnet_ifflags_cb. The only state this touches is unp_if_flags, and all paths touching it also hold IFNET_LOCK -- not to mention this is the only path that touches unp_if_flags in the first place! --- sys/dev/usb/usbnet.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index f780e98cee9f..abe51ceee46d 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -987,8 +987,6 @@ usbnet_ifflags_cb(struct ethercom *ec) KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); - mutex_enter(&unp->unp_core_lock); - const u_short changed = ifp->if_flags ^ unp->unp_if_flags; if ((changed & ~(IFF_CANTCHANGE | IFF_DEBUG)) == 0) { unp->unp_if_flags = ifp->if_flags; @@ -998,8 +996,6 @@ usbnet_ifflags_cb(struct ethercom *ec) rv = ENETRESET; } - mutex_exit(&unp->unp_core_lock); - return rv; } From f1ac83d96256aaa7dd34eb6dd5fb8c2aa4e8e00f Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 14:26:56 +0000 Subject: [PATCH 45/77] usbnet drivers: Omit needless uno_init locked subroutines. uno_init is now called with the core lock already held so there is no need for a separate locked subroutine. --- sys/dev/usb/if_aue.c | 12 +----------- sys/dev/usb/if_axe.c | 10 +--------- sys/dev/usb/if_axen.c | 10 +--------- sys/dev/usb/if_cue.c | 12 +----------- sys/dev/usb/if_kue.c | 12 +----------- sys/dev/usb/if_mos.c | 10 +--------- sys/dev/usb/if_mue.c | 12 +----------- sys/dev/usb/if_smsc.c | 9 --------- sys/dev/usb/if_ure.c | 10 +--------- sys/dev/usb/if_url.c | 10 +--------- 10 files changed, 9 insertions(+), 98 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index 058c8ae923be..9cc622a1368c 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -954,7 +954,7 @@ aue_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) } static int -aue_init_locked(struct ifnet *ifp) +aue_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; struct aue_softc *sc = usbnet_softc(un); @@ -1000,16 +1000,6 @@ aue_init_locked(struct ifnet *ifp) return rv; } -static int -aue_uno_init(struct ifnet *ifp) -{ - int rv; - - rv = aue_init_locked(ifp); - - return rv; -} - static void aue_uno_mcast(struct ifnet *ifp) { diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index ea22523cc651..1286dcf944fb 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -1210,7 +1210,7 @@ axe_csum_cfg(struct axe_softc *sc) } static int -axe_init_locked(struct ifnet *ifp) +axe_uno_init(struct ifnet *ifp) { AXEHIST_FUNC(); AXEHIST_CALLED(); struct usbnet * const un = ifp->if_softc; @@ -1306,14 +1306,6 @@ axe_init_locked(struct ifnet *ifp) return usbnet_init_rx_tx(un); } -static int -axe_uno_init(struct ifnet *ifp) -{ - int ret = axe_init_locked(ifp); - - return ret; -} - static void axe_uno_mcast(struct ifnet *ifp) { diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index ae07b34b0daa..6db947dd38e2 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -894,7 +894,7 @@ axen_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) } static int -axen_init_locked(struct ifnet *ifp) +axen_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; uint16_t rxmode; @@ -932,14 +932,6 @@ axen_init_locked(struct ifnet *ifp) return usbnet_init_rx_tx(un); } -static int -axen_uno_init(struct ifnet *ifp) -{ - int ret = axen_init_locked(ifp); - - return ret; -} - static void axen_uno_stop(struct ifnet *ifp, int disable) { diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index 646cef9178b5..6fc62f924e10 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -613,7 +613,7 @@ cue_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) } static int -cue_init_locked(struct ifnet *ifp) +cue_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; int i, ctl; @@ -667,16 +667,6 @@ cue_init_locked(struct ifnet *ifp) return usbnet_init_rx_tx(un); } -static int -cue_uno_init(struct ifnet *ifp) -{ - int rv; - - rv = cue_init_locked(ifp); - - return rv; -} - static void cue_uno_mcast(struct ifnet *ifp) { diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index c02f40a77dcf..265c981f4d41 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -591,7 +591,7 @@ kue_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) } static int -kue_init_locked(struct ifnet *ifp) +kue_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; struct kue_softc *sc = usbnet_softc(un); @@ -627,16 +627,6 @@ kue_init_locked(struct ifnet *ifp) return usbnet_init_rx_tx(un); } -static int -kue_uno_init(struct ifnet *ifp) -{ - int rv; - - rv = kue_init_locked(ifp); - - return rv; -} - static void kue_uno_mcast(struct ifnet *ifp) { diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index 1c27bcb6f308..2e0799a15ebd 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -723,7 +723,7 @@ mos_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) } static int -mos_init_locked(struct ifnet *ifp) +mos_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; u_int8_t rxmode; @@ -759,14 +759,6 @@ mos_init_locked(struct ifnet *ifp) return usbnet_init_rx_tx(un); } -static int -mos_uno_init(struct ifnet *ifp) -{ - int ret = mos_init_locked(ifp); - - return ret; -} - static void mos_uno_mcast(struct ifnet *ifp) { diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index d6ab282aa2d7..3f360bded2f6 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1223,7 +1223,7 @@ mue_uno_rx_loop(struct usbnet *un, struct usbnet_chain *c, uint32_t total_len) } static int -mue_init_locked(struct ifnet *ifp) +mue_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; @@ -1253,16 +1253,6 @@ mue_init_locked(struct ifnet *ifp) return usbnet_init_rx_tx(un); } -static int -mue_uno_init(struct ifnet *ifp) -{ - int rv; - - rv = mue_init_locked(ifp); - - return rv; -} - static int mue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) { diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index a48336f8b972..7fac2e4a2497 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -174,7 +174,6 @@ static int smsc_chip_init(struct usbnet *); static int smsc_setmacaddress(struct usbnet *, const uint8_t *); static int smsc_uno_init(struct ifnet *); -static int smsc_init_locked(struct ifnet *); static void smsc_uno_stop(struct ifnet *, int); static void smsc_reset(struct smsc_softc *); @@ -553,14 +552,6 @@ smsc_reset(struct smsc_softc *sc) static int smsc_uno_init(struct ifnet *ifp) -{ - int ret = smsc_init_locked(ifp); - - return ret; -} - -static int -smsc_init_locked(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; struct smsc_softc * const sc = usbnet_softc(un); diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index 45b18f48438c..7a49d558a6c7 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -408,7 +408,7 @@ ure_reset(struct usbnet *un) } static int -ure_init_locked(struct ifnet *ifp) +ure_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; uint8_t eaddr[8]; @@ -453,14 +453,6 @@ ure_init_locked(struct ifnet *ifp) return usbnet_init_rx_tx(un); } -static int -ure_uno_init(struct ifnet *ifp) -{ - int ret = ure_init_locked(ifp); - - return ret; -} - static void ure_uno_stop(struct ifnet *ifp, int disable __unused) { diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index 82f1772f180f..b525a7a02f85 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -363,7 +363,7 @@ url_csr_write_4(struct usbnet *un, int reg, int aval) } static int -url_init_locked(struct ifnet *ifp) +url_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; const u_char *eaddr; @@ -401,14 +401,6 @@ url_init_locked(struct ifnet *ifp) return usbnet_init_rx_tx(un); } -static int -url_uno_init(struct ifnet *ifp) -{ - int ret = url_init_locked(ifp); - - return ret; -} - static void url_reset(struct usbnet *un) { From f53ed8724210cedf15a6fc2122fafe6072da7624 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 23:17:18 +0000 Subject: [PATCH 46/77] usbnet: Take the core lock around uno_mcast. Every driver does this already. This will enable us to change the lock that serializes access to the registers so we can go back to doing this synchronously in SIOCADDMULTI/SIOCDELMULTI. --- sys/dev/usb/if_aue.c | 3 --- sys/dev/usb/if_axe.c | 4 ---- sys/dev/usb/if_axen.c | 4 ---- sys/dev/usb/if_cue.c | 4 ---- sys/dev/usb/if_kue.c | 4 ---- sys/dev/usb/if_mos.c | 4 ---- sys/dev/usb/if_mue.c | 4 ---- sys/dev/usb/if_smsc.c | 4 ---- sys/dev/usb/if_udav.c | 4 ---- sys/dev/usb/if_ure.c | 4 ---- sys/dev/usb/if_url.c | 4 ---- sys/dev/usb/usbnet.c | 5 ++++- 12 files changed, 4 insertions(+), 44 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index 9cc622a1368c..6fa49edb4962 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -1003,7 +1003,6 @@ aue_uno_init(struct ifnet *ifp) static void aue_uno_mcast(struct ifnet *ifp) { - struct usbnet * const un = ifp->if_softc; AUEHIST_FUNC(); AUEHIST_CALLARGSN(5, "aue%jd: enter", @@ -1014,9 +1013,7 @@ aue_uno_mcast(struct ifnet *ifp) * XXX I feel like this is pretty heavy-handed! Maybe we could * make do with aue_setiff_locked instead? */ - usbnet_lock_core(un); aue_uno_init(ifp); - usbnet_unlock_core(un); } static void diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index 1286dcf944fb..224eac042771 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -1311,11 +1311,7 @@ axe_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); - axe_rcvfilt_locked(un); - - usbnet_unlock_core(un); } static void diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index 6db947dd38e2..0e3334022a4e 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -574,11 +574,7 @@ axen_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); - axen_setiff_locked(un); - - usbnet_unlock_core(un); } static int diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index 6fc62f924e10..828ea1085584 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -672,11 +672,7 @@ cue_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); - cue_setiff_locked(un); - - usbnet_unlock_core(un); } /* Stop and reset the adapter. */ diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index 265c981f4d41..048a718095a3 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -632,11 +632,7 @@ kue_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); - kue_setiff_locked(un); - - usbnet_unlock_core(un); } #ifdef _MODULE diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index 2e0799a15ebd..df70e79b535a 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -764,11 +764,7 @@ mos_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); - mos_rcvfilt_locked(un); - - usbnet_unlock_core(un); } void diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index 3f360bded2f6..201a4dc3f856 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1281,11 +1281,7 @@ mue_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); - mue_setiff_locked(un); - - usbnet_unlock_core(un); } static void diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 7fac2e4a2497..429c2b939899 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -762,11 +762,7 @@ smsc_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); - smsc_setiff_locked(un); - - usbnet_unlock_core(un); } static int diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index 77f9bd353c5e..3528653f3794 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -716,11 +716,7 @@ udav_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); - udav_setiff_locked(un); - - usbnet_unlock_core(un); } /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index 7a49d558a6c7..37e3611f9c87 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -795,11 +795,7 @@ ure_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); - ure_rcvfilt_locked(un); - - usbnet_unlock_core(un); } static int diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index b525a7a02f85..35bb1e7016f2 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -550,11 +550,7 @@ url_uno_mcast(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); - url_rcvfilt_locked(un); - - usbnet_unlock_core(un); } /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index abe51ceee46d..31562ec087a7 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1060,8 +1060,11 @@ usbnet_mcast_task(void *arg) */ IFNET_LOCK(ifp); if (ifp->if_flags & IFF_RUNNING) { - if (un->un_ops->uno_mcast) + if (un->un_ops->uno_mcast) { + mutex_enter(&un->un_pri->unp_core_lock); (*un->un_ops->uno_mcast)(ifp); + mutex_exit(&un->un_pri->unp_core_lock); + } } IFNET_UNLOCK(ifp); } From c0fadd7570b89880be81b355ee386c5b4a100bec Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 23:36:08 +0000 Subject: [PATCH 47/77] aue(4): Reduce aue_uno_mcast from aue_uno_init to aue_setiff_locked. This operation only needs to update the hardware to reflect SIOCADDMULTI/SIOCDELMULTI. Not clear that everything in aue(4) needs to be reset -- in fact I'm pretty sure that's undesirable! WARNING: I have not tested this with a real aue(4) device. --- sys/dev/usb/if_aue.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index 6fa49edb4962..9292d1e73e0c 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -1009,11 +1009,7 @@ aue_uno_mcast(struct ifnet *ifp) device_unit(((struct usbnet *)(ifp->if_softc))->un_dev), 0, 0, 0); - /* - * XXX I feel like this is pretty heavy-handed! Maybe we could - * make do with aue_setiff_locked instead? - */ - aue_uno_init(ifp); + aue_setiff_locked(ifp); } static void From 3613b136675518fe76a969deee377e6c897639be Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 30 Dec 2021 23:42:29 +0000 Subject: [PATCH 48/77] usbnet drivers: Omit needless uno_mcast locked subroutines. uno_mcast is now called with the core lock already held so there is no need for a separate locked subroutine. --- sys/dev/usb/if_aue.c | 18 +++--------------- sys/dev/usb/if_axe.c | 14 +++----------- sys/dev/usb/if_axen.c | 14 +++----------- sys/dev/usb/if_cue.c | 14 +++----------- sys/dev/usb/if_kue.c | 14 +++----------- sys/dev/usb/if_mos.c | 14 +++----------- sys/dev/usb/if_mue.c | 17 ++++------------- sys/dev/usb/if_smsc.c | 14 +++----------- sys/dev/usb/if_udav.c | 15 +++------------ sys/dev/usb/if_ure.c | 14 +++----------- sys/dev/usb/if_url.c | 17 ++++------------- 11 files changed, 35 insertions(+), 130 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index 9292d1e73e0c..7d1994cfb451 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -611,10 +611,10 @@ aue_crc(void *addrv) } static void -aue_setiff_locked(struct usbnet *un) +aue_uno_mcast(struct ifnet *ifp) { + struct usbnet * const un = ifp->if_softc; struct aue_softc * const sc = usbnet_softc(un); - struct ifnet * const ifp = usbnet_ifp(un); struct ethercom * ec = usbnet_ec(un); struct ether_multi *enm; struct ether_multistep step; @@ -988,7 +988,7 @@ aue_uno_init(struct ifnet *ifp) rv = usbnet_init_rx_tx(un); /* Load the multicast filter. */ - aue_setiff_locked(un); + aue_uno_mcast(ifp); /* Enable RX and TX */ aue_csr_write_1(sc, AUE_CTL0, AUE_CTL0_RXSTAT_APPEND | AUE_CTL0_RX_ENB); @@ -1000,18 +1000,6 @@ aue_uno_init(struct ifnet *ifp) return rv; } -static void -aue_uno_mcast(struct ifnet *ifp) -{ - - AUEHIST_FUNC(); - AUEHIST_CALLARGSN(5, "aue%jd: enter", - device_unit(((struct usbnet *)(ifp->if_softc))->un_dev), - 0, 0, 0); - - aue_setiff_locked(ifp); -} - static void aue_uno_stop(struct ifnet *ifp, int disable) { diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index 224eac042771..cb42c4ce17a3 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -426,11 +426,11 @@ axe_uno_mii_statchg(struct ifnet *ifp) } static void -axe_rcvfilt_locked(struct usbnet *un) +axe_uno_mcast(struct ifnet *ifp) { AXEHIST_FUNC(); AXEHIST_CALLED(); + struct usbnet * const un = ifp->if_softc; struct axe_softc * const sc = usbnet_softc(un); - struct ifnet * const ifp = usbnet_ifp(un); struct ethercom *ec = usbnet_ec(un); struct ether_multi *enm; struct ether_multistep step; @@ -1301,19 +1301,11 @@ axe_uno_init(struct ifnet *ifp) axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); /* Accept multicast frame or run promisc. mode */ - axe_rcvfilt_locked(un); + axe_uno_mcast(ifp); return usbnet_init_rx_tx(un); } -static void -axe_uno_mcast(struct ifnet *ifp) -{ - struct usbnet * const un = ifp->if_softc; - - axe_rcvfilt_locked(un); -} - static void axe_uno_stop(struct ifnet *ifp, int disable) { diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index 0e3334022a4e..55ffb9335e3b 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -225,9 +225,9 @@ axen_uno_mii_statchg(struct ifnet *ifp) } static void -axen_setiff_locked(struct usbnet *un) +axen_uno_mcast(struct ifnet *ifp) { - struct ifnet * const ifp = usbnet_ifp(un); + struct usbnet * const un = ifp->if_softc; struct ethercom *ec = usbnet_ec(un); struct ether_multi *enm; struct ether_multistep step; @@ -569,14 +569,6 @@ axen_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) return 0; } -static void -axen_uno_mcast(struct ifnet *ifp) -{ - struct usbnet * const un = ifp->if_softc; - - axen_setiff_locked(un); -} - static int axen_match(device_t parent, cfdata_t match, void *aux) { @@ -916,7 +908,7 @@ axen_uno_init(struct ifnet *ifp) axen_setoe_locked(un); /* Program promiscuous mode and multicast filters. */ - axen_setiff_locked(un); + axen_uno_mcast(ifp); /* Enable receiver, set RX mode */ axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval); diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index 828ea1085584..cf85b72d3d57 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -357,11 +357,11 @@ cue_crc(const char *addr) } static void -cue_setiff_locked(struct usbnet *un) +cue_uno_mcast(struct ifnet *ifp) { + struct usbnet *un = ifp->if_softc; struct cue_softc *sc = usbnet_softc(un); struct ethercom *ec = usbnet_ec(un); - struct ifnet *ifp = usbnet_ifp(un); struct ether_multi *enm; struct ether_multistep step; uint32_t h, i; @@ -648,7 +648,7 @@ cue_uno_init(struct ifnet *ifp) cue_csr_write_1(un, CUE_ETHCTL, ctl); /* Load the multicast filter. */ - cue_setiff_locked(un); + cue_uno_mcast(ifp); /* * Set the number of RX and TX buffers that we want @@ -667,14 +667,6 @@ cue_uno_init(struct ifnet *ifp) return usbnet_init_rx_tx(un); } -static void -cue_uno_mcast(struct ifnet *ifp) -{ - struct usbnet * const un = ifp->if_softc; - - cue_setiff_locked(un); -} - /* Stop and reset the adapter. */ static void cue_uno_stop(struct ifnet *ifp, int disable) diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index 048a718095a3..be075ed5e65f 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -318,11 +318,11 @@ kue_load_fw(struct usbnet *un) } static void -kue_setiff_locked(struct usbnet *un) +kue_uno_mcast(struct ifnet *ifp) { + struct usbnet * un = ifp->if_softc; struct ethercom * ec = usbnet_ec(un); struct kue_softc * sc = usbnet_softc(un); - struct ifnet * const ifp = usbnet_ifp(un); struct ether_multi *enm; struct ether_multistep step; int i; @@ -622,19 +622,11 @@ kue_uno_init(struct ifnet *ifp) kue_setword(un, KUE_CMD_SET_URB_SIZE, 64); /* Load the multicast filter. */ - kue_setiff_locked(un); + kue_uno_mcast(ifp); return usbnet_init_rx_tx(un); } -static void -kue_uno_mcast(struct ifnet *ifp) -{ - struct usbnet * const un = ifp->if_softc; - - kue_setiff_locked(un); -} - #ifdef _MODULE #include "ioconf.c" #endif diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index df70e79b535a..afe02a06ed22 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -458,9 +458,9 @@ mos_uno_mii_statchg(struct ifnet *ifp) } static void -mos_rcvfilt_locked(struct usbnet *un) +mos_uno_mcast(struct ifnet *ifp) { - struct ifnet *ifp = usbnet_ifp(un); + struct usbnet *un = ifp->if_softc; struct ethercom *ec = usbnet_ec(un); struct ether_multi *enm; struct ether_multistep step; @@ -748,7 +748,7 @@ mos_uno_init(struct ifnet *ifp) mos_reg_write_1(un, MOS_IPG1, ipgs[1]); /* Accept multicast frame or run promisc. mode */ - mos_rcvfilt_locked(un); + mos_uno_mcast(ifp); /* Enable receiver and transmitter, bridge controls speed/duplex mode */ rxmode = mos_reg_read_1(un, MOS_CTL); @@ -759,14 +759,6 @@ mos_uno_init(struct ifnet *ifp) return usbnet_init_rx_tx(un); } -static void -mos_uno_mcast(struct ifnet *ifp) -{ - struct usbnet * const un = ifp->if_softc; - - mos_rcvfilt_locked(un); -} - void mos_uno_stop(struct ifnet *ifp, int disable) { diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index 201a4dc3f856..0f5c29421afc 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -92,14 +92,13 @@ static int mue_chip_init(struct usbnet *); static void mue_set_macaddr(struct usbnet *); static int mue_get_macaddr(struct usbnet *, prop_dictionary_t); static int mue_prepare_tso(struct usbnet *, struct mbuf *); -static void mue_setiff_locked(struct usbnet *); +static void mue_uno_mcast(struct ifnet *); static void mue_sethwcsum_locked(struct usbnet *); static void mue_setmtu_locked(struct usbnet *); static void mue_reset(struct usbnet *); static void mue_uno_stop(struct ifnet *, int); static int mue_uno_ioctl(struct ifnet *, u_long, void *); -static void mue_uno_mcast(struct ifnet *); static int mue_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *); static int mue_uno_mii_write_reg(struct usbnet *, int, int, uint16_t); static void mue_uno_mii_statchg(struct ifnet *); @@ -997,10 +996,10 @@ mue_prepare_tso(struct usbnet *un, struct mbuf *m) } static void -mue_setiff_locked(struct usbnet *un) +mue_uno_mcast(struct ifnet *ifp) { + struct usbnet *un = ifp->if_softc; struct ethercom *ec = usbnet_ec(un); - struct ifnet * const ifp = usbnet_ifp(un); const uint8_t *enaddr = CLLADDR(ifp->if_sadl); struct ether_multi *enm; struct ether_multistep step; @@ -1242,7 +1241,7 @@ mue_uno_init(struct ifnet *ifp) mue_set_macaddr(un); /* Load the multicast filter. */ - mue_setiff_locked(un); + mue_uno_mcast(ifp); /* TCP/UDP checksum offload engines. */ mue_sethwcsum_locked(un); @@ -1276,14 +1275,6 @@ mue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) return 0; } -static void -mue_uno_mcast(struct ifnet *ifp) -{ - struct usbnet * const un = ifp->if_softc; - - mue_setiff_locked(un); -} - static void mue_reset(struct usbnet *un) { diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 429c2b939899..57c4f08b77f0 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -411,11 +411,11 @@ smsc_hash(uint8_t addr[ETHER_ADDR_LEN]) } static void -smsc_setiff_locked(struct usbnet *un) +smsc_uno_mcast(struct ifnet *ifp) { USMSCHIST_FUNC(); USMSCHIST_CALLED(); + struct usbnet * const un = ifp->if_softc; struct smsc_softc * const sc = usbnet_softc(un); - struct ifnet * const ifp = usbnet_ifp(un); struct ethercom *ec = usbnet_ec(un); struct ether_multi *enm; struct ether_multistep step; @@ -568,7 +568,7 @@ smsc_uno_init(struct ifnet *ifp) smsc_reset(sc); /* Load the multicast filter. */ - smsc_setiff_locked(un); + smsc_uno_mcast(ifp); /* TCP/UDP checksum offload engines. */ smsc_setoe_locked(un); @@ -757,14 +757,6 @@ smsc_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) return 0; } -static void -smsc_uno_mcast(struct ifnet *ifp) -{ - struct usbnet * const un = ifp->if_softc; - - smsc_setiff_locked(un); -} - static int smsc_match(device_t parent, cfdata_t match, void *aux) { diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index 3528653f3794..791939e5d358 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -74,7 +74,6 @@ static int udav_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *); static int udav_uno_mii_write_reg(struct usbnet *, int, int, uint16_t); static void udav_uno_mii_statchg(struct ifnet *); static int udav_uno_init(struct ifnet *); -static void udav_setiff_locked(struct usbnet *); static void udav_reset(struct usbnet *); static int udav_csr_read(struct usbnet *, int, void *, int); @@ -501,7 +500,7 @@ udav_uno_init(struct ifnet *ifp) UDAV_CLRBIT(un, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC); /* Load the multicast filter */ - udav_setiff_locked(un); + udav_uno_mcast(ifp); /* Enable RX */ UDAV_SETBIT(un, UDAV_RCR, UDAV_RCR_RXEN); @@ -576,10 +575,10 @@ udav_chip_init(struct usbnet *un) (ether_crc32_le((addr), ETHER_ADDR_LEN) & ((1 << UDAV_BITS) - 1)) static void -udav_setiff_locked(struct usbnet *un) +udav_uno_mcast(struct ifnet *ifp) { + struct usbnet * const un = ifp->if_softc; struct ethercom *ec = usbnet_ec(un); - struct ifnet * const ifp = usbnet_ifp(un); struct ether_multi *enm; struct ether_multistep step; uint8_t hashes[8]; @@ -711,14 +710,6 @@ udav_uno_rx_loop(struct usbnet *un, struct usbnet_chain *c, uint32_t total_len) usbnet_enqueue(un, buf, pkt_len, 0, 0, 0); } -static void -udav_uno_mcast(struct ifnet *ifp) -{ - struct usbnet * const un = ifp->if_softc; - - udav_setiff_locked(un); -} - /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ static void udav_uno_stop(struct ifnet *ifp, int disable) diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index 37e3611f9c87..8d6da56a603a 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -331,10 +331,10 @@ ure_uno_miibus_statchg(struct ifnet *ifp) } static void -ure_rcvfilt_locked(struct usbnet *un) +ure_uno_mcast(struct ifnet *ifp) { + struct usbnet *un = ifp->if_softc; struct ethercom *ec = usbnet_ec(un); - struct ifnet *ifp = usbnet_ifp(un); struct ether_multi *enm; struct ether_multistep step; uint32_t mchash[2] = { 0, 0 }; @@ -448,7 +448,7 @@ ure_uno_init(struct ifnet *ifp) ~URE_RXDY_GATED_EN); /* Accept multicast frame or run promisc. mode. */ - ure_rcvfilt_locked(un); + ure_uno_mcast(ifp); return usbnet_init_rx_tx(un); } @@ -790,14 +790,6 @@ ure_init_fifo(struct usbnet *un) URE_TXFIFO_THR_NORMAL); } -static void -ure_uno_mcast(struct ifnet *ifp) -{ - struct usbnet * const un = ifp->if_softc; - - ure_rcvfilt_locked(un); -} - static int ure_match(device_t parent, cfdata_t match, void *aux) { diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index 35bb1e7016f2..df856a563bc4 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -77,11 +77,10 @@ static unsigned url_uno_tx_prepare(struct usbnet *, struct mbuf *, static void url_uno_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); static int url_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *); static int url_uno_mii_write_reg(struct usbnet *, int, int, uint16_t); -static void url_uno_mcast(struct ifnet *); static void url_uno_stop(struct ifnet *, int); static void url_uno_mii_statchg(struct ifnet *); static int url_uno_init(struct ifnet *); -static void url_rcvfilt_locked(struct usbnet *); +static void url_uno_mcast(struct ifnet *); static void url_reset(struct usbnet *); static int url_csr_read_1(struct usbnet *, int); @@ -393,7 +392,7 @@ url_uno_init(struct ifnet *ifp) URL_SETBIT2(un, URL_RCR, URL_RCR_TAIL | URL_RCR_AD | URL_RCR_AB); /* Accept multicast frame or run promisc. mode */ - url_rcvfilt_locked(un); + url_uno_mcast(ifp); /* Enable RX and TX */ URL_SETBIT(un, URL_CR, URL_CR_TE | URL_CR_RE); @@ -425,9 +424,9 @@ url_reset(struct usbnet *un) } static void -url_rcvfilt_locked(struct usbnet *un) +url_uno_mcast(struct ifnet *ifp) { - struct ifnet * const ifp = usbnet_ifp(un); + struct usbnet * const un = ifp->if_softc; struct ethercom *ec = usbnet_ec(un); struct ether_multi *enm; struct ether_multistep step; @@ -545,14 +544,6 @@ static void url_intr(void) } #endif -static void -url_uno_mcast(struct ifnet *ifp) -{ - struct usbnet * const un = ifp->if_softc; - - url_rcvfilt_locked(un); -} - /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ static void url_uno_stop(struct ifnet *ifp, int disable) From e6f96cbca700dab89231585416905a1f39f78a7e Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 31 Dec 2021 00:48:54 +0000 Subject: [PATCH 49/77] usbnet drivers: Stop abusing ifp->if_flags & IFF_ALLMULTI. This legacy flag is a figment of userland's imagination. The actual kernel state is ec->ec_flags & ETHER_F_ALLMULTI, protected by the ETHER_LOCK, so that multicast filter updates -- which run without IFNET_LOCK -- need not attempt to write racily to ifp->if_flags. --- sys/dev/usb/if_aue.c | 12 ++++++------ sys/dev/usb/if_cue.c | 8 ++++---- sys/dev/usb/if_kue.c | 8 ++++---- sys/dev/usb/if_mue.c | 9 ++++----- sys/dev/usb/if_smsc.c | 8 +++++--- sys/dev/usb/if_udav.c | 12 ++++++++---- 6 files changed, 31 insertions(+), 26 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index 7d1994cfb451..bd9226a3ba67 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -627,21 +627,20 @@ aue_uno_mcast(struct ifnet *ifp) usbnet_isowned_core(un); if (ifp->if_flags & IFF_PROMISC) { + ETHER_LOCK(ec); allmulti: - ifp->if_flags |= IFF_ALLMULTI; + ec->ec_flags |= ETHER_F_ALLMULTI; + ETHER_UNLOCK(ec); AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI); return; } - AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI); - /* now program new ones */ ETHER_LOCK(ec); ETHER_FIRST_MULTI(step, ec, enm); while (enm != NULL) { if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN) != 0) { - ETHER_UNLOCK(ec); goto allmulti; } @@ -649,13 +648,14 @@ allmulti: hashtbl[h >> 3] |= 1 << (h & 0x7); ETHER_NEXT_MULTI(step, enm); } + ec->ec_flags &= ~ETHER_F_ALLMULTI; ETHER_UNLOCK(ec); + AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI); + /* write the hashtable */ for (i = 0; i < 8; i++) aue_csr_write_1(sc, AUE_MAR0 + i, hashtbl[i]); - - ifp->if_flags &= ~IFF_ALLMULTI; } static void diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index cf85b72d3d57..a3902bc54679 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -370,8 +370,10 @@ cue_uno_mcast(struct ifnet *ifp) device_xname(un->un_dev), ifp->if_flags)); if (ifp->if_flags & IFF_PROMISC) { + ETHER_LOCK(ec); allmulti: - ifp->if_flags |= IFF_ALLMULTI; + ec->ec_flags |= ETHER_F_ALLMULTI; + ETHER_UNLOCK(ec); for (i = 0; i < CUE_MCAST_TABLE_LEN; i++) sc->cue_mctab[i] = 0xFF; cue_mem(un, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR, @@ -389,7 +391,6 @@ allmulti: while (enm != NULL) { if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN) != 0) { - ETHER_UNLOCK(ec); goto allmulti; } @@ -397,10 +398,9 @@ allmulti: sc->cue_mctab[h >> 3] |= 1 << (h & 0x7); ETHER_NEXT_MULTI(step, enm); } + ec->ec_flags &= ~ETHER_F_ALLMULTI; ETHER_UNLOCK(ec); - ifp->if_flags &= ~IFF_ALLMULTI; - /* * Also include the broadcast address in the filter * so we can receive broadcast frames. diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index be075ed5e65f..15f32d81409f 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -336,8 +336,10 @@ kue_uno_mcast(struct ifnet *ifp) sc->kue_rxfilt &= ~KUE_RXFILT_PROMISC; if (ifp->if_flags & IFF_PROMISC) { + ETHER_LOCK(ec); allmulti: - ifp->if_flags |= IFF_ALLMULTI; + ec->ec_flags |= ETHER_F_ALLMULTI; + ETHER_UNLOCK(ec); sc->kue_rxfilt |= KUE_RXFILT_ALLMULTI|KUE_RXFILT_PROMISC; sc->kue_rxfilt &= ~KUE_RXFILT_MULTICAST; kue_setword(un, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt); @@ -353,7 +355,6 @@ allmulti: if (i == KUE_MCFILTCNT(sc) || memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN) != 0) { - ETHER_UNLOCK(ec); goto allmulti; } @@ -361,10 +362,9 @@ allmulti: ETHER_NEXT_MULTI(step, enm); i++; } + ec->ec_flags &= ~ETHER_F_ALLMULTI; ETHER_UNLOCK(ec); - ifp->if_flags &= ~IFF_ALLMULTI; - sc->kue_rxfilt |= KUE_RXFILT_MULTICAST; kue_ctl(un, KUE_CTL_WRITE, KUE_CMD_SET_MCAST_FILTERS, i, sc->kue_mcfilters, i * ETHER_ADDR_LEN); diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index 0f5c29421afc..c63911009771 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1023,10 +1023,11 @@ mue_uno_mcast(struct ifnet *ifp) /* Always accept broadcast frames. */ rxfilt |= MUE_RFE_CTL_BROADCAST; + ETHER_LOCK(ec); if (ifp->if_flags & IFF_PROMISC) { rxfilt |= MUE_RFE_CTL_UNICAST; allmulti: rxfilt |= MUE_RFE_CTL_MULTICAST; - ifp->if_flags |= IFF_ALLMULTI; + ec->ec_flags |= ETHER_F_ALLMULTI; if (ifp->if_flags & IFF_PROMISC) DPRINTF(un, "promisc\n"); else @@ -1036,7 +1037,6 @@ allmulti: rxfilt |= MUE_RFE_CTL_MULTICAST; pfiltbl[0][0] = MUE_ENADDR_HI(enaddr) | MUE_ADDR_FILTX_VALID; pfiltbl[0][1] = MUE_ENADDR_LO(enaddr); i = 1; - ETHER_LOCK(ec); ETHER_FIRST_MULTI(step, ec, enm); while (enm != NULL) { if (memcmp(enm->enm_addrlo, enm->enm_addrhi, @@ -1044,7 +1044,6 @@ allmulti: rxfilt |= MUE_RFE_CTL_MULTICAST; memset(pfiltbl, 0, sizeof(pfiltbl)); memset(hashtbl, 0, sizeof(hashtbl)); rxfilt &= ~MUE_RFE_CTL_MULTICAST_HASH; - ETHER_UNLOCK(ec); goto allmulti; } if (i < MUE_NUM_ADDR_FILTX) { @@ -1062,14 +1061,14 @@ allmulti: rxfilt |= MUE_RFE_CTL_MULTICAST; i++; ETHER_NEXT_MULTI(step, enm); } - ETHER_UNLOCK(ec); + ec->ec_flags &= ~ETHER_F_ALLMULTI; rxfilt |= MUE_RFE_CTL_PERFECT; - ifp->if_flags &= ~IFF_ALLMULTI; if (rxfilt & MUE_RFE_CTL_MULTICAST_HASH) DPRINTF(un, "perfect filter and hash tables\n"); else DPRINTF(un, "perfect filter\n"); } + ETHER_UNLOCK(ec); for (i = 0; i < MUE_NUM_ADDR_FILTX; i++) { hireg = (un->un_flags & LAN7500) ? diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 57c4f08b77f0..751d0c982eb7 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -427,8 +427,11 @@ smsc_uno_mcast(struct ifnet *ifp) if (usbnet_isdying(un)) return; - if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) { + if (ifp->if_flags & IFF_PROMISC) { + ETHER_LOCK(ec); allmulti: + ec->ec_flags |= ETHER_F_ALLMULTI; + ETHER_UNLOCK(ec); DPRINTF("receive all multicast enabled", 0, 0, 0, 0); sc->sc_mac_csr |= SMSC_MAC_CSR_MCPAS; sc->sc_mac_csr &= ~SMSC_MAC_CSR_HPFILT; @@ -443,7 +446,6 @@ allmulti: ETHER_FIRST_MULTI(step, ec, enm); while (enm != NULL) { if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { - ETHER_UNLOCK(ec); goto allmulti; } @@ -451,6 +453,7 @@ allmulti: hashtbl[hash >> 5] |= 1 << (hash & 0x1F); ETHER_NEXT_MULTI(step, enm); } + ec->ec_flags &= ~ETHER_F_ALLMULTI; ETHER_UNLOCK(ec); /* Debug */ @@ -463,7 +466,6 @@ allmulti: /* Write the hash table and mac control registers */ //XXX should we be doing this? - ifp->if_flags &= ~IFF_ALLMULTI; smsc_writereg(un, SMSC_HASHH, hashtbl[1]); smsc_writereg(un, SMSC_HASHL, hashtbl[0]); smsc_writereg(un, SMSC_MAC_CSR, sc->sc_mac_csr); diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index 791939e5d358..32978d4d2dd5 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -598,11 +598,16 @@ udav_uno_mcast(struct ifnet *ifp) } if (ifp->if_flags & IFF_PROMISC) { + ETHER_LOCK(ec); + ec->ec_flags |= ETHER_F_ALLMULTI; + ETHER_UNLOCK(ec); UDAV_SETBIT(un, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC); return; - } else if (ifp->if_flags & IFF_ALLMULTI) { + } else if (ifp->if_flags & IFF_ALLMULTI) { /* XXX ??? Can't happen? */ + ETHER_LOCK(ec); allmulti: - ifp->if_flags |= IFF_ALLMULTI; + ec->ec_flags |= ETHER_F_ALLMULTI; + ETHER_UNLOCK(ec); UDAV_SETBIT(un, UDAV_RCR, UDAV_RCR_ALL); UDAV_CLRBIT(un, UDAV_RCR, UDAV_RCR_PRMSC); return; @@ -619,7 +624,6 @@ allmulti: while (enm != NULL) { if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN) != 0) { - ETHER_UNLOCK(ec); goto allmulti; } @@ -627,10 +631,10 @@ allmulti: hashes[h>>3] |= 1 << (h & 0x7); ETHER_NEXT_MULTI(step, enm); } + ec->ec_flags &= ~ETHER_F_ALLMULTI; ETHER_UNLOCK(ec); /* disable all multicast */ - ifp->if_flags &= ~IFF_ALLMULTI; UDAV_CLRBIT(un, UDAV_RCR, UDAV_RCR_ALL); /* write hash value to the register */ From 4163b2d36ba8559e45ecefb56d0c6783372626f5 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 7 Jan 2022 00:49:08 +0000 Subject: [PATCH 50/77] usbnet: Apply hardware multicast filter updates synchronously again. To make this work: 1. Do it only under a new lock, unp_mcastlock. This lock lives at IPL_SOFTCLOCK so it can be taken from network stack callouts. It is forbidden to acquire the usbnet core lock under unp_mcastlock. 2. Do it only after usbnet_init_rx_tx and before usbnet_stop; if issued at any other time, drop the update on the floor. 3. Make usbnet_init_rx_tx apply any pending multicast filter updates under the lock before setting the flag that allows SIOCADDMULTI or SIOCDELMULTI to apply the updates. 4. Remove core lock asserts from various drivers' register access routines. This is necessary because the multicast filter updates are done with register reads/writes, but _cannot_ take the core lock when the caller holds softnet_lock. This now programs the hardware multicast filter redundantly in many drivers which already explicitly call *_uno_mcast from the *_uno_init routines. This is probably harmless, but it will likely be better to remove the explicit calls. --- sys/dev/usb/if_aue.c | 10 ---- sys/dev/usb/if_axe.c | 2 - sys/dev/usb/if_axen.c | 4 -- sys/dev/usb/if_smsc.c | 6 -- sys/dev/usb/if_udav.c | 7 --- sys/dev/usb/if_ure.c | 2 - sys/dev/usb/if_url.c | 4 -- sys/dev/usb/usbnet.c | 124 +++++++++++++++--------------------------- 8 files changed, 43 insertions(+), 116 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index bd9226a3ba67..60e1551bfa77 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -284,8 +284,6 @@ aue_csr_read_1(struct aue_softc *sc, int reg) usbd_status err; uByte val = 0; - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return 0; @@ -315,8 +313,6 @@ aue_csr_read_2(struct aue_softc *sc, int reg) usbd_status err; uWord val; - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return 0; @@ -346,8 +342,6 @@ aue_csr_write_1(struct aue_softc *sc, int reg, int aval) usbd_status err; uByte val; - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return 0; @@ -378,8 +372,6 @@ aue_csr_write_2(struct aue_softc *sc, int reg, int aval) usbd_status err; uWord val; - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return 0; @@ -624,8 +616,6 @@ aue_uno_mcast(struct ifnet *ifp) AUEHIST_FUNC(); AUEHIST_CALLARGSN(5, "aue%jd: enter", device_unit(un->un_dev), 0, 0, 0); - usbnet_isowned_core(un); - if (ifp->if_flags & IFF_PROMISC) { ETHER_LOCK(ec); allmulti: diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index cb42c4ce17a3..a62af4a7d4eb 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -293,8 +293,6 @@ axe_cmd(struct axe_softc *sc, int cmd, int index, int val, void *buf) usb_device_request_t req; usbd_status err; - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return -1; diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index 55ffb9335e3b..910ef4602199 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -108,8 +108,6 @@ axen_cmd(struct usbnet *un, int cmd, int index, int val, void *buf) usb_device_request_t req; usbd_status err; - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return 0; @@ -239,8 +237,6 @@ axen_uno_mcast(struct ifnet *ifp) if (usbnet_isdying(un)) return; - usbnet_isowned_core(un); - rxmode = 0; /* Enable receiver, set RX mode */ diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 751d0c982eb7..7de0a5e1fb27 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -211,8 +211,6 @@ smsc_readreg(struct usbnet *un, uint32_t off, uint32_t *data) uint32_t buf; usbd_status err; - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return 0; @@ -238,8 +236,6 @@ smsc_writereg(struct usbnet *un, uint32_t off, uint32_t data) uint32_t buf; usbd_status err; - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return 0; @@ -422,8 +418,6 @@ smsc_uno_mcast(struct ifnet *ifp) uint32_t hashtbl[2] = { 0, 0 }; uint32_t hash; - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return; diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index 32978d4d2dd5..fb443e0afb33 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -364,7 +364,6 @@ udav_csr_read(struct usbnet *un, int offset, void *buf, int len) usb_device_request_t req; usbd_status err; - usbnet_isowned_core(un); KASSERT(!usbnet_isdying(un)); DPRINTFN(0x200, @@ -395,7 +394,6 @@ udav_csr_write(struct usbnet *un, int offset, void *buf, int len) usb_device_request_t req; usbd_status err; - usbnet_isowned_core(un); KASSERT(!usbnet_isdying(un)); DPRINTFN(0x200, @@ -424,8 +422,6 @@ udav_csr_read1(struct usbnet *un, int offset) { uint8_t val = 0; - usbnet_isowned_core(un); - DPRINTFN(0x200, ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); @@ -442,7 +438,6 @@ udav_csr_write1(struct usbnet *un, int offset, unsigned char ch) usb_device_request_t req; usbd_status err; - usbnet_isowned_core(un); KASSERT(!usbnet_isdying(un)); DPRINTFN(0x200, @@ -586,8 +581,6 @@ udav_uno_mcast(struct ifnet *ifp) DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return; diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index 8d6da56a603a..7a2ebd311ded 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -340,8 +340,6 @@ ure_uno_mcast(struct ifnet *ifp) uint32_t mchash[2] = { 0, 0 }; uint32_t h = 0, rxmode; - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return; diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index df856a563bc4..9dbf779aea31 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -268,8 +268,6 @@ url_mem(struct usbnet *un, int cmd, int offset, void *buf, int len) usb_device_request_t req; usbd_status err; - usbnet_isowned_core(un); - DPRINTFN(0x200, ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); @@ -435,8 +433,6 @@ url_uno_mcast(struct ifnet *ifp) DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return; diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 31562ec087a7..1c8210d07a8b 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -59,6 +59,7 @@ struct usbnet_private { * * the lock ordering is: * ifnet lock -> unp_core_lock -> unp_rxlock -> unp_txlock + * -> unp_mcastlock * - ifnet lock is not needed for unp_core_lock, but if ifnet lock is * involved, it must be taken first */ @@ -66,11 +67,13 @@ struct usbnet_private { kmutex_t unp_rxlock; kmutex_t unp_txlock; + kmutex_t unp_mcastlock; + bool unp_mcastactive; + struct usbnet_cdata unp_cdata; struct ethercom unp_ec; struct mii_data unp_mii; - struct usb_task unp_mcasttask; struct usb_task unp_ticktask; struct callout unp_stat_ch; struct usbd_pipe *unp_ep[USBNET_ENDPT_MAX]; @@ -866,6 +869,17 @@ usbnet_init_rx_tx(struct usbnet * const un) "%s", ifp->if_xname); ifp->if_flags |= IFF_RUNNING; + /* + * If the hardware has a multicast filter, program it and then + * allow updates to it while we're running. + */ + if (un->un_ops->uno_mcast) { + mutex_enter(&unp->unp_mcastlock); + (*un->un_ops->uno_mcast)(ifp); + unp->unp_mcastactive = true; + mutex_exit(&unp->unp_mcastlock); + } + /* Start up the receive pipe(s). */ usbnet_rx_start_pipes(un); @@ -1018,8 +1032,20 @@ usbnet_if_ioctl(struct ifnet *ifp, u_long cmd, void *data) switch (cmd) { case SIOCADDMULTI: case SIOCDELMULTI: - usb_add_task(un->un_udev, &unp->unp_mcasttask, - USB_TASKQ_DRIVER); + /* + * If there's a hardware multicast filter, and + * it has been programmed by usbnet_init_rx_tx + * and is active, update it now. Otherwise, + * drop the update on the floor -- it will be + * observed by usbnet_init_rx_tx next time we + * bring the interface up. + */ + if (un->un_ops->uno_mcast) { + mutex_enter(&unp->unp_mcastlock); + if (unp->unp_mcastactive) + (*un->un_ops->uno_mcast)(ifp); + mutex_exit(&unp->unp_mcastlock); + } error = 0; break; default: @@ -1030,45 +1056,6 @@ usbnet_if_ioctl(struct ifnet *ifp, u_long cmd, void *data) return error; } -static void -usbnet_mcast_task(void *arg) -{ - USBNETHIST_FUNC(); - struct usbnet * const un = arg; - struct ifnet * const ifp = usbnet_ifp(un); - - USBNETHIST_CALLARGSN(10, "%jd: enter", - un->un_pri->unp_number, 0, 0, 0); - - /* - * If we're detaching, we must check usbnet_isdying _before_ - * touching IFNET_LOCK -- the ifnet may have been detached by - * the time this task runs. This is racy -- unp_dying may be - * set immediately after we test it -- but nevertheless safe, - * because usbnet_detach waits for the task to complete before - * issuing if_detach, and necessary, so that we don't touch - * IFNET_LOCK after if_detach. See usbnet_detach for details. - */ - if (usbnet_isdying(un)) - return; - - /* - * If the hardware is running, ask the driver to reprogram the - * multicast filter. If the hardware is not running, the - * driver is responsible for programming the multicast filter - * as part of its uno_init routine to bring the hardware up. - */ - IFNET_LOCK(ifp); - if (ifp->if_flags & IFF_RUNNING) { - if (un->un_ops->uno_mcast) { - mutex_enter(&un->un_pri->unp_core_lock); - (*un->un_ops->uno_mcast)(ifp); - mutex_exit(&un->un_pri->unp_core_lock); - } - } - IFNET_UNLOCK(ifp); -} - /* * Generic stop network function: * - mark as stopping @@ -1093,6 +1080,18 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) "%s", ifp->if_xname); usbnet_isowned_core(un); + /* + * For drivers with hardware multicast filter update callbacks: + * Prevent concurrent access to the hardware registers by + * multicast filter updates, which happens without IFNET_LOCK + * or the usbnet core lock. + */ + if (un->un_ops->uno_mcast) { + mutex_enter(&unp->unp_mcastlock); + unp->unp_mcastactive = false; + mutex_exit(&unp->unp_mcastlock); + } + /* * Prevent new activity (rescheduling ticks, xfers, &c.) and * clear the watchdog timer. @@ -1387,8 +1386,6 @@ usbnet_attach(struct usbnet *un, un->un_pri = kmem_zalloc(sizeof(*un->un_pri), KM_SLEEP); struct usbnet_private * const unp = un->un_pri; - usb_init_task(&unp->unp_mcasttask, usbnet_mcast_task, un, - USB_TASKQ_MPSAFE); usb_init_task(&unp->unp_ticktask, usbnet_tick_task, un, USB_TASKQ_MPSAFE); callout_init(&unp->unp_stat_ch, CALLOUT_MPSAFE); @@ -1397,6 +1394,7 @@ usbnet_attach(struct usbnet *un, mutex_init(&unp->unp_txlock, MUTEX_DEFAULT, IPL_SOFTUSB); mutex_init(&unp->unp_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB); mutex_init(&unp->unp_core_lock, MUTEX_DEFAULT, IPL_NONE); + mutex_init(&unp->unp_mcastlock, MUTEX_DEFAULT, IPL_SOFTCLOCK); rnd_attach_source(&unp->unp_rndsrc, device_xname(un->un_dev), RND_TYPE_NET, RND_FLAG_DEFAULT); @@ -1539,9 +1537,6 @@ usbnet_detach(device_t self, int flags) KASSERT(!callout_pending(&unp->unp_stat_ch)); KASSERT(!usb_task_pending(un->un_udev, &unp->unp_ticktask)); - usb_rem_task_wait(un->un_udev, &unp->unp_mcasttask, USB_TASKQ_DRIVER, - NULL); - if (mii) { mii_detach(mii, MII_PHY_ANY, MII_OFFSET_ANY); ifmedia_fini(&mii->mii_media); @@ -1555,45 +1550,12 @@ usbnet_detach(device_t self, int flags) } usbnet_ec(un)->ec_mii = NULL; - /* - * We have already waited for the multicast task to complete. - * Unfortunately, until if_detach, nothing has prevented it - * from running again -- another thread might issue if_mcast_op - * between the time of our first usb_rem_task_wait and the time - * we actually get around to if_detach. - * - * Fortunately, the first usb_rem_task_wait ensures that if the - * task is scheduled again, it will witness our setting of - * unp_dying to true[*]. So after that point, if the task is - * scheduled again, it will decline to touch IFNET_LOCK and do - * nothing. But we still need to wait for it to complete. - * - * It would be nice if we could write - * - * if_pleasestopissuingmcastopsthanks(ifp); - * usb_rem_task_wait(..., &unp->unp_mcasttask, ...); - * if_detach(ifp); - * - * and then we would need only one usb_rem_task_wait. - * - * Unfortunately, there is no such operation available in - * sys/net at the moment, and it would require a bit of - * coordination with if_mcast_op and doifioctl probably under a - * new lock. So we'll use this kludge until that mechanism is - * invented. - * - * [*] This is not exactly a documented property of the API, - * but it is implied by the single lock in the task queue - * serializing changes to the task state. - */ - usb_rem_task_wait(un->un_udev, &unp->unp_mcasttask, USB_TASKQ_DRIVER, - NULL); - usbnet_rx_list_free(un); usbnet_tx_list_free(un); rnd_detach_source(&unp->unp_rndsrc); + mutex_destroy(&unp->unp_mcastlock); mutex_destroy(&unp->unp_core_lock); mutex_destroy(&unp->unp_rxlock); mutex_destroy(&unp->unp_txlock); From 5151d123bad3603ce59b91e132c692964ba17612 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 7 Jan 2022 00:57:08 +0000 Subject: [PATCH 51/77] usbnet drivers: Omit redundant multicast filter update on init. --- sys/dev/usb/if_aue.c | 3 --- sys/dev/usb/if_axe.c | 3 --- sys/dev/usb/if_axen.c | 3 --- sys/dev/usb/if_cue.c | 3 --- sys/dev/usb/if_kue.c | 3 --- sys/dev/usb/if_mos.c | 3 --- sys/dev/usb/if_mue.c | 3 --- sys/dev/usb/if_smsc.c | 3 --- sys/dev/usb/if_udav.c | 3 --- sys/dev/usb/if_ure.c | 3 --- sys/dev/usb/if_url.c | 3 --- 11 files changed, 33 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index 60e1551bfa77..4c46c11a9862 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -977,9 +977,6 @@ aue_uno_init(struct ifnet *ifp) rv = usbnet_init_rx_tx(un); - /* Load the multicast filter. */ - aue_uno_mcast(ifp); - /* Enable RX and TX */ aue_csr_write_1(sc, AUE_CTL0, AUE_CTL0_RXSTAT_APPEND | AUE_CTL0_RX_ENB); AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_TX_ENB); diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index a62af4a7d4eb..641148ae9af4 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -1298,9 +1298,6 @@ axe_uno_init(struct ifnet *ifp) axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); - /* Accept multicast frame or run promisc. mode */ - axe_uno_mcast(ifp); - return usbnet_init_rx_tx(un); } diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index 910ef4602199..d70a8ef553d6 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -903,9 +903,6 @@ axen_uno_init(struct ifnet *ifp) /* Configure offloading engine. */ axen_setoe_locked(un); - /* Program promiscuous mode and multicast filters. */ - axen_uno_mcast(ifp); - /* Enable receiver, set RX mode */ axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval); rxmode = le16toh(wval); diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index a3902bc54679..de78422bead6 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -647,9 +647,6 @@ cue_uno_init(struct ifnet *ifp) ctl |= CUE_ETHCTL_PROMISC; cue_csr_write_1(un, CUE_ETHCTL, ctl); - /* Load the multicast filter. */ - cue_uno_mcast(ifp); - /* * Set the number of RX and TX buffers that we want * to reserve inside the ASIC. diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index 15f32d81409f..76ada5e2c2fc 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -621,9 +621,6 @@ kue_uno_init(struct ifnet *ifp) #endif kue_setword(un, KUE_CMD_SET_URB_SIZE, 64); - /* Load the multicast filter. */ - kue_uno_mcast(ifp); - return usbnet_init_rx_tx(un); } diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index afe02a06ed22..8c9483c16bc4 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -747,9 +747,6 @@ mos_uno_init(struct ifnet *ifp) mos_reg_write_1(un, MOS_IPG0, ipgs[0]); mos_reg_write_1(un, MOS_IPG1, ipgs[1]); - /* Accept multicast frame or run promisc. mode */ - mos_uno_mcast(ifp); - /* Enable receiver and transmitter, bridge controls speed/duplex mode */ rxmode = mos_reg_read_1(un, MOS_CTL); rxmode |= MOS_CTL_RX_ENB | MOS_CTL_TX_ENB | MOS_CTL_BS_ENB; diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index c63911009771..0e9c23ac14a5 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1239,9 +1239,6 @@ mue_uno_init(struct ifnet *ifp) /* Set MAC address. */ mue_set_macaddr(un); - /* Load the multicast filter. */ - mue_uno_mcast(ifp); - /* TCP/UDP checksum offload engines. */ mue_sethwcsum_locked(un); diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 7de0a5e1fb27..4662dcf1a4ee 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -563,9 +563,6 @@ smsc_uno_init(struct ifnet *ifp) /* Reset the ethernet interface. */ smsc_reset(sc); - /* Load the multicast filter. */ - smsc_uno_mcast(ifp); - /* TCP/UDP checksum offload engines. */ smsc_setoe_locked(un); diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index fb443e0afb33..be74ad58ca0f 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -494,9 +494,6 @@ udav_uno_init(struct ifnet *ifp) else UDAV_CLRBIT(un, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC); - /* Load the multicast filter */ - udav_uno_mcast(ifp); - /* Enable RX */ UDAV_SETBIT(un, UDAV_RCR, UDAV_RCR_RXEN); diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index 7a2ebd311ded..307cdd71d007 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -445,9 +445,6 @@ ure_uno_init(struct ifnet *ifp) ure_read_2(un, URE_PLA_MISC_1, URE_MCU_TYPE_PLA) & ~URE_RXDY_GATED_EN); - /* Accept multicast frame or run promisc. mode. */ - ure_uno_mcast(ifp); - return usbnet_init_rx_tx(un); } diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index 9dbf779aea31..0efb6afb2a7f 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -389,9 +389,6 @@ url_uno_init(struct ifnet *ifp) /* Init receive control register */ URL_SETBIT2(un, URL_RCR, URL_RCR_TAIL | URL_RCR_AD | URL_RCR_AB); - /* Accept multicast frame or run promisc. mode */ - url_uno_mcast(ifp); - /* Enable RX and TX */ URL_SETBIT(un, URL_CR, URL_CR_TE | URL_CR_RE); From a1f61b14e6a81fd316231bb11ff2c79f5e5d5b12 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 7 Jan 2022 01:23:12 +0000 Subject: [PATCH 52/77] aue(4): Enable rx/tx registers on init before usbnet_init_rx_tx. This way, we still have exclusive access to the registers before calls to aue_uno_mcast can start happening without the usbnet core lock. --- sys/dev/usb/if_aue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index 4c46c11a9862..70b97c038c62 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -975,13 +975,13 @@ aue_uno_init(struct ifnet *ifp) else AUE_CLRBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC); - rv = usbnet_init_rx_tx(un); - /* Enable RX and TX */ aue_csr_write_1(sc, AUE_CTL0, AUE_CTL0_RXSTAT_APPEND | AUE_CTL0_RX_ENB); AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_TX_ENB); AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_EP3_CLR); + rv = usbnet_init_rx_tx(un); + //mii_mediachg(mii); return rv; From ddce7318e0d3a16d600237371e3030158425d894 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 7 Jan 2022 01:26:28 +0000 Subject: [PATCH 53/77] aue(4): Simplify. No functional change. --- sys/dev/usb/if_aue.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index 70b97c038c62..b2af18bd825f 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -948,7 +948,7 @@ aue_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; struct aue_softc *sc = usbnet_softc(un); - int i, rv; + int i; const u_char *eaddr; AUEHIST_FUNC(); @@ -980,11 +980,7 @@ aue_uno_init(struct ifnet *ifp) AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_TX_ENB); AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_EP3_CLR); - rv = usbnet_init_rx_tx(un); - - //mii_mediachg(mii); - - return rv; + return usbnet_init_rx_tx(un); } static void From b214c792ed6bf4260659b30a5f210234b464064e Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 7 Jan 2022 01:41:50 +0000 Subject: [PATCH 54/77] udav(4): Stop asserting !usbnet_isdying. This can change at any moment; no software lock can prevent the device from being detached. Any test of it is necessarily best-effort just to avoid wasting time later on waiting for requests to fail or time out. --- sys/dev/usb/if_udav.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index be74ad58ca0f..4585f90a279e 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -364,7 +364,8 @@ udav_csr_read(struct usbnet *un, int offset, void *buf, int len) usb_device_request_t req; usbd_status err; - KASSERT(!usbnet_isdying(un)); + if (usbnet_isdying(un)) + return USBD_IOERROR; DPRINTFN(0x200, ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); @@ -394,7 +395,8 @@ udav_csr_write(struct usbnet *un, int offset, void *buf, int len) usb_device_request_t req; usbd_status err; - KASSERT(!usbnet_isdying(un)); + if (usbnet_isdying(un)) + return USBD_IOERROR; DPRINTFN(0x200, ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); @@ -438,7 +440,8 @@ udav_csr_write1(struct usbnet *un, int offset, unsigned char ch) usb_device_request_t req; usbd_status err; - KASSERT(!usbnet_isdying(un)); + if (usbnet_isdying(un)) + return USBD_IOERROR; DPRINTFN(0x200, ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); From 613ee2050e124e844e5f8d69eb160a925dc3a3aa Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 7 Jan 2022 01:46:34 +0000 Subject: [PATCH 55/77] usbnet drivers: Assert IFNET_LOCKED in if ioctl routines. These only happen either during the transition up or down (init or stop), or while that transition is excluded (ioctl). This may be called from ioctl or from init, which both hold the ifnet lock. XXX smsc_setoe_locked should maybe trigger reinit because the rx loop behaves differently depending on whether checksumming is enabled. XXX mue_sethwcsum_locked needs to exclude mcast updates. --- sys/dev/usb/if_axen.c | 2 +- sys/dev/usb/if_mue.c | 4 ++++ sys/dev/usb/if_smsc.c | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index d70a8ef553d6..92127d30dfb0 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -516,7 +516,7 @@ axen_setoe_locked(struct usbnet *un) uint64_t enabled = ifp->if_capenable; uint8_t val; - usbnet_isowned_core(un); + KASSERT(IFNET_LOCKED(ifp)); val = AXEN_RXCOE_OFF; if (enabled & IFCAP_CSUM_IPv4_Rx) diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index 0e9c23ac14a5..8747b24e55b2 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1091,6 +1091,8 @@ mue_sethwcsum_locked(struct usbnet *un) struct ifnet * const ifp = usbnet_ifp(un); uint32_t reg, val; + KASSERT(IFNET_LOCKED(ifp)); + reg = (un->un_flags & LAN7500) ? MUE_7500_RFE_CTL : MUE_7800_RFE_CTL; val = mue_csr_read(un, reg); @@ -1123,6 +1125,8 @@ mue_setmtu_locked(struct usbnet *un) struct ifnet * const ifp = usbnet_ifp(un); uint32_t val; + KASSERT(IFNET_LOCKED(ifp)); + /* Set the maximum frame size. */ MUE_CLRBIT(un, MUE_MAC_RX, MUE_MAC_RX_RXEN); val = mue_csr_read(un, MUE_MAC_RX); diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 4662dcf1a4ee..9119d796335a 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -473,7 +473,7 @@ smsc_setoe_locked(struct usbnet *un) uint32_t val; int err; - usbnet_isowned_core(un); + KASSERT(IFNET_LOCKED(ifp)); err = smsc_readreg(un, SMSC_COE_CTRL, &val); if (err != 0) { From 245b2fb8c9445f34265e76372fb7e3b9f32b5d21 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 9 Jan 2022 00:37:15 +0000 Subject: [PATCH 56/77] axen(4): Use axen mii read/write reg routines, not usbnet ones. The usbnet wrappers don't add anything important. We already test usbnet_isdying in axen_cmd, and that's already a best-effort thing (which should probably be done better by having usbd_do_request fail promptly if detaching anyway). --- sys/dev/usb/if_axen.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index 92127d30dfb0..cfe5d92591dc 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -492,18 +492,18 @@ axen_ax88179_init(struct usbnet *un) #define GMII_PHY_PAGE_SEL 0x1e #define GMII_PHY_PAGE_SEL 0x1f #define GMII_PAGE_EXT 0x0007 - usbnet_mii_writereg(un->un_dev, un->un_phyno, GMII_PHY_PAGE_SEL, + axen_uno_mii_write_reg(un, un->un_phyno, GMII_PHY_PAGE_SEL, GMII_PAGE_EXT); - usbnet_mii_writereg(un->un_dev, un->un_phyno, GMII_PHY_PAGE, + axen_uno_mii_write_reg(un, un->un_phyno, GMII_PHY_PAGE, 0x002c); #endif #if 1 /* XXX: phy hack ? */ - usbnet_mii_writereg(un->un_dev, un->un_phyno, 0x1F, 0x0005); - usbnet_mii_writereg(un->un_dev, un->un_phyno, 0x0C, 0x0000); - usbnet_mii_readreg(un->un_dev, un->un_phyno, 0x0001, &wval); - usbnet_mii_writereg(un->un_dev, un->un_phyno, 0x01, wval | 0x0080); - usbnet_mii_writereg(un->un_dev, un->un_phyno, 0x1F, 0x0000); + axen_uno_mii_write_reg(un, un->un_phyno, 0x1F, 0x0005); + axen_uno_mii_write_reg(un, un->un_phyno, 0x0C, 0x0000); + axen_uno_mii_read_reg(un, un->un_phyno, 0x0001, &wval); + axen_uno_mii_write_reg(un, un->un_phyno, 0x01, wval | 0x0080); + axen_uno_mii_write_reg(un, un->un_phyno, 0x1F, 0x0000); #endif usbnet_unlock_core(un); From 18d091c9f23ea70e7671a1993bb0a1a923bff829 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 9 Jan 2022 00:39:16 +0000 Subject: [PATCH 57/77] usbnet drivers: Avoid undefined behaviour if read reg fails. Some callers don't check the error code, e.g. ~all the mii phy drivers using PHY_READ. Just return zero if the device is gone or the xfer fails for any other reason. --- sys/dev/usb/if_aue.c | 9 +++++++-- sys/dev/usb/if_axe.c | 5 ++++- sys/dev/usb/if_axen.c | 8 ++++++-- sys/dev/usb/if_mos.c | 5 ++++- sys/dev/usb/if_mue.c | 6 +++++- sys/dev/usb/if_smsc.c | 6 +++++- sys/dev/usb/if_udav.c | 3 +++ sys/dev/usb/if_ure.c | 6 +++++- sys/dev/usb/if_url.c | 8 +++++++- 9 files changed, 46 insertions(+), 10 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index b2af18bd825f..64b1f481cc7f 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -466,8 +466,10 @@ aue_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) */ if (sc->aue_vendor == USB_VENDOR_ADMTEK && sc->aue_product == USB_PRODUCT_ADMTEK_PEGASUS) { - if (phy == 3) + if (phy == 3) { + *val = 0; return EINVAL; + } } #endif @@ -475,8 +477,10 @@ aue_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_READ); for (i = 0; i < AUE_TIMEOUT; i++) { - if (usbnet_isdying(un)) + if (usbnet_isdying(un)) { + *val = 0; return ENXIO; + } if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE) break; } @@ -484,6 +488,7 @@ aue_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) if (i == AUE_TIMEOUT) { AUEHIST_CALLARGS("aue%jd: phy=%#jx reg=%#jx read timed out", device_unit(un->un_dev), phy, reg, 0); + *val = 0; return ETIMEDOUT; } diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index 641148ae9af4..8b87e9835fac 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -324,8 +324,10 @@ axe_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) DPRINTFN(30, "phy %#jx reg %#jx\n", phy, reg, 0, 0); - if (un->un_phyno != phy) + if (un->un_phyno != phy) { + *val = 0; return EINVAL; + } axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL); @@ -334,6 +336,7 @@ axe_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) if (err) { device_printf(un->un_dev, "read PHY failed\n"); + *val = 0; return EIO; } diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index cfe5d92591dc..eb33c6c0aaed 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -137,12 +137,16 @@ axen_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) { uint16_t data; - if (un->un_phyno != phy) + if (un->un_phyno != phy) { + *val = 0; return EINVAL; + } usbd_status err = axen_cmd(un, AXEN_CMD_MII_READ_REG, reg, phy, &data); - if (err) + if (err) { + *val = 0; return EIO; + } *val = le16toh(data); if (reg == MII_BMSR) diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index 8c9483c16bc4..fa38e7c49ec7 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -364,13 +364,16 @@ mos_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) MOS_PHYSTS_PENDING); for (i = 0; i < MOS_TIMEOUT; i++) { - if (usbnet_isdying(un)) + if (usbnet_isdying(un)) { + *val = 0; return ENXIO; + } if (mos_reg_read_1(un, MOS_PHY_STS) & MOS_PHYSTS_READY) break; } if (i == MOS_TIMEOUT) { aprint_error_dev(un->un_dev, "read PHY failed\n"); + *val = 0; return EIO; } diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index 8747b24e55b2..d7564459c4de 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -219,11 +219,14 @@ mue_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) { uint32_t data; - if (un->un_phyno != phy) + if (un->un_phyno != phy) { + *val = 0; return EINVAL; + } if (MUE_WAIT_CLR(un, MUE_MII_ACCESS, MUE_MII_ACCESS_BUSY, 0)) { MUE_PRINTF(un, "not ready\n"); + *val = 0; return EBUSY; } @@ -233,6 +236,7 @@ mue_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) if (MUE_WAIT_CLR(un, MUE_MII_ACCESS, MUE_MII_ACCESS_BUSY, 0)) { MUE_PRINTF(un, "timed out\n"); + *val = 0; return ETIMEDOUT; } diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 9119d796335a..2e6ca23650c1 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -279,11 +279,14 @@ smsc_uno_miibus_readreg(struct usbnet *un, int phy, int reg, uint16_t *val) uint32_t addr; uint32_t data = 0; - if (un->un_phyno != phy) + if (un->un_phyno != phy) { + *val = 0; return EINVAL; + } if (smsc_wait_for_bits(un, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) { smsc_warn_printf(un, "MII is busy\n"); + *val = 0; return ETIMEDOUT; } @@ -292,6 +295,7 @@ smsc_uno_miibus_readreg(struct usbnet *un, int phy, int reg, uint16_t *val) if (smsc_wait_for_bits(un, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) { smsc_warn_printf(un, "MII read timeout\n"); + *val = 0; return ETIMEDOUT; } diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index 4585f90a279e..e41f4a406f96 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -383,6 +383,7 @@ udav_csr_read(struct usbnet *un, int offset, void *buf, int len) if (err) { DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n", device_xname(un->un_dev), __func__, offset, err)); + memset(buf, 0, len); } return err; @@ -731,6 +732,7 @@ udav_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) printf("%s: %s: dying\n", device_xname(un->un_dev), __func__); #endif + *val = 0; return EINVAL; } @@ -738,6 +740,7 @@ udav_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) if (phy != 0) { DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", device_xname(un->un_dev), __func__, phy)); + *val = 0; return EINVAL; } diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index 307cdd71d007..f83d7d9a1150 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -137,6 +137,8 @@ ure_ctl(struct usbnet *un, uint8_t rw, uint16_t val, uint16_t index, err = usbd_do_request(un->un_udev, &req, buf); if (err) { DPRINTF(("ure_ctl: error %d\n", err)); + if (rw == URE_CTL_READ) + memset(buf, 0, len); return -1; } @@ -277,8 +279,10 @@ static int ure_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) { - if (un->un_phyno != phy) + if (un->un_phyno != phy) { + *val = 0; return EINVAL; + } /* Let the rgephy driver read the URE_PLA_PHYSTATUS register. */ if (reg == RTK_GMEDIASTAT) { diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index 0efb6afb2a7f..6e5f47141b89 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -271,8 +271,11 @@ url_mem(struct usbnet *un, int cmd, int offset, void *buf, int len) DPRINTFN(0x200, ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - if (usbnet_isdying(un)) + if (usbnet_isdying(un)) { + if (cmd == URL_CMD_READMEM) + memset(buf, 0, len); return 0; + } if (cmd == URL_CMD_READMEM) req.bmRequestType = UT_READ_VENDOR_DEVICE; @@ -289,6 +292,8 @@ url_mem(struct usbnet *un, int cmd, int offset, void *buf, int len) device_xname(un->un_dev), cmd == URL_CMD_READMEM ? "read" : "write", offset, err)); + if (cmd == URL_CMD_READMEM) + memset(buf, 0, len); } return err; @@ -561,6 +566,7 @@ url_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) if (phy != 0) { DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", device_xname(un->un_dev), __func__, phy)); + *val = 0; return EINVAL; } From 48387e9ad236f0270979f6461ee973158863ae62 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 9 Jan 2022 00:39:47 +0000 Subject: [PATCH 58/77] usbnet: Make usbnet_mii_readreg/writereg/statchg private to usbnet.c. No drivers need to use these. --- sys/dev/usb/usbnet.c | 6 +++--- sys/dev/usb/usbnet.h | 5 ----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 1c8210d07a8b..2bf19e2a1662 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -899,7 +899,7 @@ out: /* MII management. */ -int +static int usbnet_mii_readreg(device_t dev, int phy, int reg, uint16_t *val) { USBNETHIST_FUNC(); @@ -923,7 +923,7 @@ usbnet_mii_readreg(device_t dev, int phy, int reg, uint16_t *val) return 0; } -int +static int usbnet_mii_writereg(device_t dev, int phy, int reg, uint16_t val) { USBNETHIST_FUNC(); @@ -947,7 +947,7 @@ usbnet_mii_writereg(device_t dev, int phy, int reg, uint16_t val) return 0; } -void +static void usbnet_mii_statchg(struct ifnet *ifp) { USBNETHIST_FUNC(); USBNETHIST_CALLED(); diff --git a/sys/dev/usb/usbnet.h b/sys/dev/usb/usbnet.h index 7ade49a0bd34..f48417602a08 100644 --- a/sys/dev/usb/usbnet.h +++ b/sys/dev/usb/usbnet.h @@ -326,11 +326,6 @@ usbnet_isowned_core(struct usbnet *un) */ int usbnet_init_rx_tx(struct usbnet * const); -/* MII. */ -int usbnet_mii_readreg(device_t, int, int, uint16_t *); -int usbnet_mii_writereg(device_t, int, int, uint16_t); -void usbnet_mii_statchg(struct ifnet *); - /* interrupt handling */ void usbnet_enqueue(struct usbnet * const, uint8_t *, size_t, int, uint32_t, int); From 547ed30322bf34b076e8f51187335ec60a8ccad0 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 7 Jan 2022 01:43:32 +0000 Subject: [PATCH 59/77] usbnet drivers: Omit needless usbnet core lock and assertions. During attach, the caller has exclusive access to the usbnet until usbnet_attach_ifp. At other times, register access is serialized either by the usbnet multicast lock or by IFNET_LOCK. --- sys/dev/usb/if_aue.c | 6 ------ sys/dev/usb/if_axe.c | 9 --------- sys/dev/usb/if_axen.c | 15 --------------- sys/dev/usb/if_cue.c | 4 ---- sys/dev/usb/if_mue.c | 4 ---- sys/dev/usb/if_smsc.c | 11 ----------- sys/dev/usb/if_udav.c | 5 ----- sys/dev/usb/if_ure.c | 6 ------ sys/dev/usb/if_url.c | 5 ----- 9 files changed, 65 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index 64b1f481cc7f..6e44c572d33e 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -432,8 +432,6 @@ aue_read_mac(struct usbnet *un) int off = 0; int word; - usbnet_isowned_core(un); - AUEHIST_FUNC(); AUEHIST_CALLARGS("aue%jd: enter", device_unit(un->un_dev), 0, 0, 0); @@ -851,14 +849,10 @@ aue_attach(device_t parent, device_t self, void *aux) /* First level attach. */ usbnet_attach(un, "auedet"); - usbnet_lock_core(un); - /* Reset the adapter and get station address from the EEPROM. */ aue_reset(sc); aue_read_mac(un); - usbnet_unlock_core(un); - usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 0, &unm); } diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index 8b87e9835fac..6b00869cda03 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -513,8 +513,6 @@ static void axe_reset(struct usbnet *un) { - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return; @@ -930,10 +928,8 @@ axe_attach(device_t parent, device_t self, void *aux) usbnet_attach(un, "axedet"); /* We need the PHYID for init dance in some cases */ - usbnet_lock_core(un); if (axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, &sc->axe_phyaddrs)) { aprint_error_dev(self, "failed to read phyaddrs\n"); - usbnet_unlock_core(un); return; } @@ -963,13 +959,10 @@ axe_attach(device_t parent, device_t self, void *aux) } else { if (axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, sc->axe_ipgs)) { aprint_error_dev(self, "failed to read ipg\n"); - usbnet_unlock_core(un); return; } } - usbnet_unlock_core(un); - if (!AXE_IS_172(un)) usbnet_ec(un)->ec_capabilities = ETHERCAP_VLAN_MTU; if (un->un_flags & AX772B) { @@ -1218,8 +1211,6 @@ axe_uno_init(struct ifnet *ifp) struct axe_softc * const sc = usbnet_softc(un); int rxmode; - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return EIO; diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index eb33c6c0aaed..0a5bc6a9d5c3 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -295,7 +295,6 @@ allmulti: static void axen_reset(struct usbnet *un) { - usbnet_isowned_core(un); if (usbnet_isdying(un)) return; /* XXX What to reset? */ @@ -367,8 +366,6 @@ axen_ax88179_init(struct usbnet *un) uint16_t wval; uint8_t val; - usbnet_lock_core(un); - /* XXX: ? */ axen_cmd(un, AXEN_CMD_MAC_READ, 1, AXEN_UNK_05, &val); DPRINTFN(5, ("AXEN_CMD_MAC_READ(0x05): 0x%02x\n", val)); @@ -451,7 +448,6 @@ axen_ax88179_init(struct usbnet *un) default: aprint_error_dev(un->un_dev, "unknown uplink bus:0x%02x\n", val); - usbnet_unlock_core(un); return; } axen_cmd(un, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL, &qctrl); @@ -509,8 +505,6 @@ axen_ax88179_init(struct usbnet *un) axen_uno_mii_write_reg(un, un->un_phyno, 0x01, wval | 0x0080); axen_uno_mii_write_reg(un, un->un_phyno, 0x1F, 0x0000); #endif - - usbnet_unlock_core(un); } static void @@ -554,8 +548,6 @@ axen_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); - switch (cmd) { case SIOCSIFCAP: axen_setoe_locked(un); @@ -564,8 +556,6 @@ axen_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) break; } - usbnet_unlock_core(un); - return 0; } @@ -666,13 +656,10 @@ axen_attach(device_t parent, device_t self, void *aux) DPRINTF(("%s: phyno %d\n", device_xname(self), un->un_phyno)); /* Get station address. */ - usbnet_lock_core(un); if (axen_get_eaddr(un, &un->un_eaddr)) { - usbnet_unlock_core(un); printf("EEPROM checksum error\n"); return; } - usbnet_unlock_core(un); axen_ax88179_init(un); @@ -889,8 +876,6 @@ axen_uno_init(struct ifnet *ifp) uint16_t wval; uint8_t bval; - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return EIO; diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index de78422bead6..951836df49de 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -545,8 +545,6 @@ cue_uno_tick(struct usbnet *un) { struct ifnet *ifp = usbnet_ifp(un); - usbnet_lock_core(un); - net_stat_ref_t nsr = IF_STAT_GETREF(ifp); if (cue_csr_read_2(un, CUE_RX_FRAMEERR)) if_statinc_ref(nsr, if_ierrors); @@ -558,8 +556,6 @@ cue_uno_tick(struct usbnet *un) if_statadd_ref(nsr, if_collisions, cue_csr_read_2(un, CUE_TX_EXCESSCOLL)); IF_STAT_PUTREF(ifp); - - usbnet_unlock_core(un); } static void diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index d7564459c4de..1eea5855b912 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1261,8 +1261,6 @@ mue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); - switch (cmd) { case SIOCSIFCAP: mue_sethwcsum_locked(un); @@ -1274,8 +1272,6 @@ mue_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) break; } - usbnet_unlock_core(un); - return 0; } diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 2e6ca23650c1..4ab8a895b9f6 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -539,7 +539,6 @@ smsc_reset(struct smsc_softc *sc) { struct usbnet * const un = &sc->smsc_un; - usbnet_isowned_core(un); if (usbnet_isdying(un)) return; @@ -556,8 +555,6 @@ smsc_uno_init(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; struct smsc_softc * const sc = usbnet_softc(un); - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return EIO; @@ -591,8 +588,6 @@ smsc_chip_init(struct usbnet *un) int burst_cap; int err; - usbnet_isowned_core(un); - /* Enter H/W config mode */ smsc_writereg(un, SMSC_HW_CFG, SMSC_HW_CFG_LRST); @@ -739,8 +734,6 @@ smsc_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) { struct usbnet * const un = ifp->if_softc; - usbnet_lock_core(un); - switch (cmd) { case SIOCSIFCAP: smsc_setoe_locked(un); @@ -749,8 +742,6 @@ smsc_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) break; } - usbnet_unlock_core(un); - return 0; } @@ -859,7 +850,6 @@ smsc_attach(device_t parent, device_t self, void *aux) /* Setup some of the basics */ un->un_phyno = 1; - usbnet_lock_core(un); /* * Attempt to get the mac address, if an EEPROM is not attached this * will just return FF:FF:FF:FF:FF:FF, so in such cases we invent a MAC @@ -887,7 +877,6 @@ smsc_attach(device_t parent, device_t self, void *aux) un->un_eaddr[0] = (uint8_t)((mac_l) & 0xff); } } - usbnet_unlock_core(un); usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 0, &unm); diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index e41f4a406f96..868e02375df6 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -238,14 +238,11 @@ udav_attach(device_t parent, device_t self, void *aux) usbnet_attach(un, "udavdet"); - usbnet_lock_core(un); - // /* reset the adapter */ // udav_reset(un); /* Get Ethernet Address */ err = udav_csr_read(un, UDAV_PAR, un->un_eaddr, ETHER_ADDR_LEN); - usbnet_unlock_core(un); if (err) { aprint_error_dev(self, "read MAC address failed\n"); return; @@ -523,7 +520,6 @@ udav_uno_init(struct ifnet *ifp) static void udav_reset(struct usbnet *un) { - usbnet_isowned_core(un); if (usbnet_isdying(un)) return; @@ -536,7 +532,6 @@ udav_reset(struct usbnet *un) static void udav_chip_init(struct usbnet *un) { - usbnet_isowned_core(un); /* Select PHY */ #if 1 diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index f83d7d9a1150..52faff4b4174 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -393,8 +393,6 @@ ure_reset(struct usbnet *un) { int i; - usbnet_isowned_core(un); - ure_write_1(un, URE_PLA_CR, URE_MCU_TYPE_PLA, URE_CR_RST); for (i = 0; i < URE_TIMEOUT; i++) { @@ -415,8 +413,6 @@ ure_uno_init(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; uint8_t eaddr[8]; - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return EIO; @@ -899,7 +895,6 @@ ure_attach(device_t parent, device_t self, void *aux) (un->un_flags != 0) ? "" : "unknown ", ver); - usbnet_lock_core(un); if (un->un_flags & URE_FLAG_8152) ure_rtl8152_init(un); else @@ -912,7 +907,6 @@ ure_attach(device_t parent, device_t self, void *aux) else ure_read_mem(un, URE_PLA_BACKUP, URE_MCU_TYPE_PLA, eaddr, sizeof(eaddr)); - usbnet_unlock_core(un); if (ETHER_IS_ZERO(eaddr)) { maclo = 0x00f2 | (cprng_strong32() & 0xffff0000); machi = cprng_strong32() & 0xffff; diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index 6e5f47141b89..dffe724ef544 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -242,15 +242,12 @@ url_attach(device_t parent, device_t self, void *aux) /* Set these up now for url_mem(). */ usbnet_attach(un, "urldet"); - usbnet_lock_core(un); - /* reset the adapter */ url_reset(un); /* Get Ethernet Address */ err = url_mem(un, URL_CMD_READMEM, URL_IDR0, (void *)un->un_eaddr, ETHER_ADDR_LEN); - usbnet_unlock_core(un); if (err) { aprint_error_dev(self, "read MAC address failed\n"); return; @@ -373,8 +370,6 @@ url_uno_init(struct ifnet *ifp) DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - usbnet_isowned_core(un); - if (usbnet_isdying(un)) return EIO; From bc6de75e9b0dea110465f943947460e66a320dbc Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 7 Jan 2022 02:01:16 +0000 Subject: [PATCH 60/77] urndis(4): Delete some crazy logic that I think is unnecessary. XXX definitely need to test this one --- sys/dev/usb/if_urndis.c | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/sys/dev/usb/if_urndis.c b/sys/dev/usb/if_urndis.c index ff4da0414739..e14df42ef03f 100644 --- a/sys/dev/usb/if_urndis.c +++ b/sys/dev/usb/if_urndis.c @@ -866,16 +866,6 @@ urndis_init_un(struct ifnet *ifp, struct usbnet *un) if (err != RNDIS_STATUS_SUCCESS) return EIO; - usbnet_lock_core(un); - if (usbnet_isdying(un)) - err = EIO; - else { - usbnet_stop(un, ifp, 1); - err = usbnet_init_rx_tx(un); - usbnet_set_link(un, err == 0); - } - usbnet_unlock_core(un); - return err; } @@ -887,9 +877,11 @@ urndis_uno_init(struct ifnet *ifp) KASSERT(IFNET_LOCKED(ifp)); - usbnet_unlock_core(un); error = urndis_init_un(ifp, un); - usbnet_lock_core(un); + if (error) + return EIO; /* XXX */ + error = usbnet_init_rx_tx(un); + usbnet_set_link(un, error == 0); return error; } @@ -1064,9 +1056,6 @@ urndis_attach(device_t parent, device_t self, void *aux) &buf, &bufsz) != RNDIS_STATUS_SUCCESS) { aprint_error("%s: unable to get hardware address\n", DEVNAME(un)); - usbnet_lock_core(un); - usbnet_stop(un, ifp, 1); - usbnet_unlock_core(un); return; } @@ -1077,9 +1066,6 @@ urndis_attach(device_t parent, device_t self, void *aux) aprint_error("%s: invalid address\n", DEVNAME(un)); if (buf && bufsz) kmem_free(buf, bufsz); - usbnet_lock_core(un); - usbnet_stop(un, ifp, 1); - usbnet_unlock_core(un); return; } @@ -1090,17 +1076,9 @@ urndis_attach(device_t parent, device_t self, void *aux) if (urndis_ctrl_set(un, OID_GEN_CURRENT_PACKET_FILTER, &filter, sizeof(filter)) != RNDIS_STATUS_SUCCESS) { aprint_error("%s: unable to set data filters\n", DEVNAME(un)); - usbnet_lock_core(un); - usbnet_stop(un, ifp, 1); - usbnet_unlock_core(un); return; } - /* Turn off again now it has been identified. */ - usbnet_lock_core(un); - usbnet_stop(un, ifp, 1); - usbnet_unlock_core(un); - usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 0, NULL); } From 26dd937f77564e5a86d1478e1afe2948e5c8f7ab Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 7 Jan 2022 02:01:44 +0000 Subject: [PATCH 61/77] usbnet: Delete the core lock from the API. Init/stop and ioctl happen under IFNET_LOCK. Multicast updates only happen after init and before stop. Core lock is no longer a relevant part of the API. Internally, it serves essentially just to lock out asynchronous mii activity during init/stop. --- sys/dev/usb/usbnet.c | 30 ++++++++++++------------------ sys/dev/usb/usbnet.h | 14 -------------- 2 files changed, 12 insertions(+), 32 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 2bf19e2a1662..a2c3f5be364e 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -102,6 +102,18 @@ volatile unsigned usbnet_number; static void usbnet_isowned_rx(struct usbnet *); static void usbnet_isowned_tx(struct usbnet *); +static kmutex_t * +usbnet_mutex_core(struct usbnet *un) +{ + return &un->un_pri->unp_core_lock; +} + +static __inline__ void +usbnet_isowned_core(struct usbnet *un) +{ + KASSERT(mutex_owned(usbnet_mutex_core(un))); +} + static int usbnet_modcmd(modcmd_t, void *); #ifdef USB_DEBUG @@ -1312,24 +1324,6 @@ usbnet_isdying(struct usbnet *un) /* Locking. */ -void -usbnet_lock_core(struct usbnet *un) -{ - mutex_enter(&un->un_pri->unp_core_lock); -} - -void -usbnet_unlock_core(struct usbnet *un) -{ - mutex_exit(&un->un_pri->unp_core_lock); -} - -kmutex_t* -usbnet_mutex_core(struct usbnet *un) -{ - return &un->un_pri->unp_core_lock; -} - static void usbnet_isowned_rx(struct usbnet *un) { diff --git a/sys/dev/usb/usbnet.h b/sys/dev/usb/usbnet.h index f48417602a08..0a6190e6dc10 100644 --- a/sys/dev/usb/usbnet.h +++ b/sys/dev/usb/usbnet.h @@ -297,20 +297,6 @@ void *usbnet_softc(struct usbnet *); bool usbnet_havelink(struct usbnet *); bool usbnet_isdying(struct usbnet *); - -/* - * Locking. Note that the isowned() are implemented here so that - * empty-KASSERT() causes them to be elided for non-DIAG builds. - */ -void usbnet_lock_core(struct usbnet *); -void usbnet_unlock_core(struct usbnet *); -kmutex_t *usbnet_mutex_core(struct usbnet *); -static __inline__ void -usbnet_isowned_core(struct usbnet *un) -{ - KASSERT(mutex_owned(usbnet_mutex_core(un))); -} - /* * Endpoint / rx/tx chain management: * From eb9f4a8bf1e682f2f9d4606af2f9d5358d621242 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 8 Jan 2022 03:04:12 +0000 Subject: [PATCH 62/77] usbnet drivers: Omit needless isdying tests in *_uno_init. usbnet(9) already checks this immediately before calling *_uno_init. --- sys/dev/usb/if_aue.c | 3 --- sys/dev/usb/if_axe.c | 3 --- sys/dev/usb/if_axen.c | 3 --- sys/dev/usb/if_cdce.c | 10 +++------- sys/dev/usb/if_cue.c | 3 --- sys/dev/usb/if_kue.c | 3 --- sys/dev/usb/if_mos.c | 3 --- sys/dev/usb/if_mue.c | 5 ----- sys/dev/usb/if_smsc.c | 3 --- sys/dev/usb/if_udav.c | 4 ---- sys/dev/usb/if_upl.c | 5 +---- sys/dev/usb/if_ure.c | 3 --- sys/dev/usb/if_url.c | 3 --- 13 files changed, 4 insertions(+), 47 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index 6e44c572d33e..d8f7250e4a00 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -954,9 +954,6 @@ aue_uno_init(struct ifnet *ifp) AUEHIST_CALLARGSN(5, "aue%jd: enter link=%jd", device_unit(un->un_dev), usbnet_havelink(un), 0, 0); - if (usbnet_isdying(un)) - return EIO; - /* Cancel pending I/O */ if (ifp->if_flags & IFF_RUNNING) return 0; diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index 6b00869cda03..95832f2d64a9 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -1211,9 +1211,6 @@ axe_uno_init(struct ifnet *ifp) struct axe_softc * const sc = usbnet_softc(un); int rxmode; - if (usbnet_isdying(un)) - return EIO; - /* Cancel pending I/O */ usbnet_stop(un, ifp, 1); diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index 0a5bc6a9d5c3..b3cbdf9e5369 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -876,9 +876,6 @@ axen_uno_init(struct ifnet *ifp) uint16_t wval; uint8_t bval; - if (usbnet_isdying(un)) - return EIO; - /* Cancel pending I/O */ usbnet_stop(un, ifp, 1); diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c index c7ee6bef2792..96c70139625c 100644 --- a/sys/dev/usb/if_cdce.c +++ b/sys/dev/usb/if_cdce.c @@ -261,13 +261,9 @@ cdce_uno_init(struct ifnet *ifp) struct usbnet *un = ifp->if_softc; int rv; - if (usbnet_isdying(un)) - rv = EIO; - else { - usbnet_stop(un, ifp, 1); - rv = usbnet_init_rx_tx(un); - usbnet_set_link(un, rv == 0); - } + usbnet_stop(un, ifp, 1); + rv = usbnet_init_rx_tx(un); + usbnet_set_link(un, rv == 0); return rv; } diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index 951836df49de..c6a2d7060fb0 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -617,9 +617,6 @@ cue_uno_init(struct ifnet *ifp) DPRINTFN(10,("%s: %s: enter\n", device_xname(un->un_dev),__func__)); - if (usbnet_isdying(un)) - return ENXIO; - /* Cancel pending I/O */ usbnet_stop(un, ifp, 1); diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index 76ada5e2c2fc..f2c2bbb66280 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -599,9 +599,6 @@ kue_uno_init(struct ifnet *ifp) DPRINTFN(5,("%s: %s: enter\n", device_xname(un->un_dev),__func__)); - if (usbnet_isdying(un)) - return EIO; - /* Cancel pending I/O */ usbnet_stop(un, ifp, 1); diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index fa38e7c49ec7..588099640723 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -732,9 +732,6 @@ mos_uno_init(struct ifnet *ifp) u_int8_t rxmode; unsigned char ipgs[2]; - if (usbnet_isdying(un)) - return EIO; - /* Cancel pending I/O */ usbnet_stop(un, ifp, 1); diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index 1eea5855b912..1151a14726dc 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1233,11 +1233,6 @@ mue_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - if (usbnet_isdying(un)) { - DPRINTF(un, "dying\n"); - return EIO; - } - /* Cancel pending I/O and free all TX/RX buffers. */ if (ifp->if_flags & IFF_RUNNING) usbnet_stop(un, ifp, 1); diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 4ab8a895b9f6..8e1d4bdabe13 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -555,9 +555,6 @@ smsc_uno_init(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; struct smsc_softc * const sc = usbnet_softc(un); - if (usbnet_isdying(un)) - return EIO; - /* Cancel pending I/O */ usbnet_stop(un, ifp, 1); diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index 868e02375df6..4b6a4e6a1733 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -471,10 +471,6 @@ udav_uno_init(struct ifnet *ifp) DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - if (usbnet_isdying(un)) { - return EIO; - } - /* Cancel pending I/O and free all TX/RX buffers */ if (ifp->if_flags & IFF_RUNNING) usbnet_stop(un, ifp, 1); diff --git a/sys/dev/usb/if_upl.c b/sys/dev/usb/if_upl.c index cf4ba9de209f..f90f644cf6b8 100644 --- a/sys/dev/usb/if_upl.c +++ b/sys/dev/usb/if_upl.c @@ -257,10 +257,7 @@ upl_uno_init(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; int rv; - if (usbnet_isdying(un)) - rv = EIO; - else - rv = usbnet_init_rx_tx(un); + rv = usbnet_init_rx_tx(un); return rv; } diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index 52faff4b4174..af9365aedc15 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -413,9 +413,6 @@ ure_uno_init(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; uint8_t eaddr[8]; - if (usbnet_isdying(un)) - return EIO; - /* Cancel pending I/O. */ if (ifp->if_flags & IFF_RUNNING) usbnet_stop(un, ifp, 1); diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index dffe724ef544..3c2e0cd52adc 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -370,9 +370,6 @@ url_uno_init(struct ifnet *ifp) DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - if (usbnet_isdying(un)) - return EIO; - /* Cancel pending I/O and free all TX/RX buffers */ usbnet_stop(un, ifp, 1); From 96a42b0916d77fcb3a242ce5c6758dce9a5159c4 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 8 Jan 2022 03:10:08 +0000 Subject: [PATCH 63/77] usbnet: Do nothing on if_init/stop if already in the target state. The network stack _shouldn't_ ever call us if so, but I'm not yet sure it _won't_. --- sys/dev/usb/usbnet.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index a2c3f5be364e..08f99fc2727c 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1162,6 +1162,16 @@ usbnet_if_stop(struct ifnet *ifp, int disable) KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); + /* + * If we're already stopped, nothing to do. + * + * XXX This should be an assertion, but it may require some + * analysis -- and possibly some tweaking -- of sys/net to + * ensure. + */ + if ((ifp->if_flags & IFF_RUNNING) == 0) + return; + mutex_enter(&unp->unp_core_lock); usbnet_stop(un, ifp, disable); mutex_exit(&unp->unp_core_lock); @@ -1263,6 +1273,16 @@ usbnet_if_init(struct ifnet *ifp) if (usbnet_isdying(un)) return EIO; + /* + * If we're already running, nothing to do. + * + * XXX This should be an assertion, but it may require some + * analysis -- and possibly some tweaking -- of sys/net to + * ensure. + */ + if (ifp->if_flags & IFF_RUNNING) + return 0; + mutex_enter(&un->un_pri->unp_core_lock); error = uno_init(un, ifp); mutex_exit(&un->un_pri->unp_core_lock); From e05ae323470f56518af381a84f9565812ad17831 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 8 Jan 2022 03:13:46 +0000 Subject: [PATCH 64/77] usbnet drivers: Prune dead IFF_RUNNING branches in *_uno_init. usbnet(9) guarantees !IFF_RUNNING now before calling it. --- sys/dev/usb/if_aue.c | 4 ---- sys/dev/usb/if_mue.c | 4 ---- sys/dev/usb/if_udav.c | 4 ---- sys/dev/usb/if_ure.c | 4 ---- sys/dev/usb/if_urndis.c | 3 --- 5 files changed, 19 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index d8f7250e4a00..55f9d86c1dd5 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -954,10 +954,6 @@ aue_uno_init(struct ifnet *ifp) AUEHIST_CALLARGSN(5, "aue%jd: enter link=%jd", device_unit(un->un_dev), usbnet_havelink(un), 0, 0); - /* Cancel pending I/O */ - if (ifp->if_flags & IFF_RUNNING) - return 0; - /* Reset the interface. */ aue_reset(sc); diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index 1151a14726dc..bdb1a8c34a05 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1233,10 +1233,6 @@ mue_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - /* Cancel pending I/O and free all TX/RX buffers. */ - if (ifp->if_flags & IFF_RUNNING) - usbnet_stop(un, ifp, 1); - mue_reset(un); /* Set MAC address. */ diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index 4b6a4e6a1733..21228ee725bd 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -471,10 +471,6 @@ udav_uno_init(struct ifnet *ifp) DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - /* Cancel pending I/O and free all TX/RX buffers */ - if (ifp->if_flags & IFF_RUNNING) - usbnet_stop(un, ifp, 1); - memcpy(eaddr, CLLADDR(ifp->if_sadl), sizeof(eaddr)); udav_csr_write(un, UDAV_PAR, eaddr, ETHER_ADDR_LEN); diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index af9365aedc15..f39322237f33 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -413,10 +413,6 @@ ure_uno_init(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; uint8_t eaddr[8]; - /* Cancel pending I/O. */ - if (ifp->if_flags & IFF_RUNNING) - usbnet_stop(un, ifp, 1); - /* Set MAC address. */ memset(eaddr, 0, sizeof(eaddr)); memcpy(eaddr, CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN); diff --git a/sys/dev/usb/if_urndis.c b/sys/dev/usb/if_urndis.c index e14df42ef03f..593d817e077b 100644 --- a/sys/dev/usb/if_urndis.c +++ b/sys/dev/usb/if_urndis.c @@ -859,9 +859,6 @@ urndis_init_un(struct ifnet *ifp, struct usbnet *un) { int err; - if (ifp->if_flags & IFF_RUNNING) - return 0; - err = urndis_ctrl_init(un); if (err != RNDIS_STATUS_SUCCESS) return EIO; From c19ce61f53efe27593b32f5b1ccb0afc9d7e4b80 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 8 Jan 2022 03:19:31 +0000 Subject: [PATCH 65/77] usbnet drivers: From *_uno_init, call *_uno_stop, not usbnet_stop. Make usbnet_stop private now that no drivers use it. None of the driver-independent logic in usbnet_stop has any effect at this point because we are guaranteed not to be running, so only the driver-dependent logic in *_uno_stop (at most) is needed. For drivers with no *_uno_stop, just omit the call to usbnet_stop altogether. Some of this logic is obviously redundant with the subsequent call to *_reset -- to be addressed in a subsequent commit. --- sys/dev/usb/if_axe.c | 2 +- sys/dev/usb/if_axen.c | 2 +- sys/dev/usb/if_cdce.c | 1 - sys/dev/usb/if_cue.c | 2 +- sys/dev/usb/if_kue.c | 3 --- sys/dev/usb/if_mos.c | 2 +- sys/dev/usb/if_smsc.c | 2 +- sys/dev/usb/if_url.c | 2 +- sys/dev/usb/usbnet.c | 4 +--- sys/dev/usb/usbnet.h | 3 --- 10 files changed, 7 insertions(+), 16 deletions(-) diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index 95832f2d64a9..c00ad888db7b 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -1212,7 +1212,7 @@ axe_uno_init(struct ifnet *ifp) int rxmode; /* Cancel pending I/O */ - usbnet_stop(un, ifp, 1); + axe_uno_stop(ifp, 1); /* Reset the ethernet interface. */ axe_reset(un); diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index b3cbdf9e5369..edc2f195642c 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -877,7 +877,7 @@ axen_uno_init(struct ifnet *ifp) uint8_t bval; /* Cancel pending I/O */ - usbnet_stop(un, ifp, 1); + axen_uno_stop(ifp, 1); /* Reset the ethernet interface. */ axen_reset(un); diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c index 96c70139625c..0b658fb0d2f0 100644 --- a/sys/dev/usb/if_cdce.c +++ b/sys/dev/usb/if_cdce.c @@ -261,7 +261,6 @@ cdce_uno_init(struct ifnet *ifp) struct usbnet *un = ifp->if_softc; int rv; - usbnet_stop(un, ifp, 1); rv = usbnet_init_rx_tx(un); usbnet_set_link(un, rv == 0); diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index c6a2d7060fb0..188f2fa173de 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -618,7 +618,7 @@ cue_uno_init(struct ifnet *ifp) DPRINTFN(10,("%s: %s: enter\n", device_xname(un->un_dev),__func__)); /* Cancel pending I/O */ - usbnet_stop(un, ifp, 1); + cue_uno_stop(ifp, 1); /* Reset the interface. */ #if 1 diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index f2c2bbb66280..3e63405dc650 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -599,9 +599,6 @@ kue_uno_init(struct ifnet *ifp) DPRINTFN(5,("%s: %s: enter\n", device_xname(un->un_dev),__func__)); - /* Cancel pending I/O */ - usbnet_stop(un, ifp, 1); - memcpy(eaddr, CLLADDR(ifp->if_sadl), sizeof(eaddr)); /* Set MAC address */ kue_ctl(un, KUE_CTL_WRITE, KUE_CMD_SET_MAC, 0, eaddr, ETHER_ADDR_LEN); diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index 588099640723..e245885918e8 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -733,7 +733,7 @@ mos_uno_init(struct ifnet *ifp) unsigned char ipgs[2]; /* Cancel pending I/O */ - usbnet_stop(un, ifp, 1); + mos_uno_stop(ifp, 1); /* Reset the ethernet interface. */ mos_reset(un); diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 8e1d4bdabe13..0353f51233f8 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -556,7 +556,7 @@ smsc_uno_init(struct ifnet *ifp) struct smsc_softc * const sc = usbnet_softc(un); /* Cancel pending I/O */ - usbnet_stop(un, ifp, 1); + smsc_uno_stop(ifp, 1); /* Reset the ethernet interface. */ smsc_reset(sc); diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index 3c2e0cd52adc..880a47b781d2 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -371,7 +371,7 @@ url_uno_init(struct ifnet *ifp) DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); /* Cancel pending I/O and free all TX/RX buffers */ - usbnet_stop(un, ifp, 1); + url_uno_stop(ifp, 1); eaddr = CLLADDR(ifp->if_sadl); for (i = 0; i < ETHER_ADDR_LEN; i++) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 08f99fc2727c..709aca405de4 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1077,11 +1077,9 @@ usbnet_if_ioctl(struct ifnet *ifp, u_long cmd, void *data) * - free RX and TX resources * - close pipes * - * usbnet_stop() is exported for drivers to use, expects lock held. - * * usbnet_if_stop() is for the if_stop handler. */ -void +static void usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) { struct usbnet_private * const unp = un->un_pri; diff --git a/sys/dev/usb/usbnet.h b/sys/dev/usb/usbnet.h index 0a6190e6dc10..bd5750bf3c5d 100644 --- a/sys/dev/usb/usbnet.h +++ b/sys/dev/usb/usbnet.h @@ -324,9 +324,6 @@ void usbnet_attach_ifp(struct usbnet *, unsigned, unsigned, int usbnet_detach(device_t, int); int usbnet_activate(device_t, devact_t); -/* stop backend */ -void usbnet_stop(struct usbnet *, struct ifnet *, int); - /* module hook up */ #ifdef _MODULE From a0b3e7200d230d81ee961250c100144f2da41c09 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 8 Jan 2022 03:25:51 +0000 Subject: [PATCH 66/77] usbnet drivers: Omit redundant device reset via *_uno_stop on init. Only those drivers where *_uno_stop is just *_reset, and *_uno_init immediately calls *_reset afterward, are affected. --- sys/dev/usb/if_axe.c | 3 --- sys/dev/usb/if_mos.c | 3 --- sys/dev/usb/if_smsc.c | 3 --- 3 files changed, 9 deletions(-) diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index c00ad888db7b..3e3c4140e8fc 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -1211,9 +1211,6 @@ axe_uno_init(struct ifnet *ifp) struct axe_softc * const sc = usbnet_softc(un); int rxmode; - /* Cancel pending I/O */ - axe_uno_stop(ifp, 1); - /* Reset the ethernet interface. */ axe_reset(un); diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index e245885918e8..6d5a4c6f5f4c 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -732,9 +732,6 @@ mos_uno_init(struct ifnet *ifp) u_int8_t rxmode; unsigned char ipgs[2]; - /* Cancel pending I/O */ - mos_uno_stop(ifp, 1); - /* Reset the ethernet interface. */ mos_reset(un); diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 0353f51233f8..c1a5967ebd0b 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -555,9 +555,6 @@ smsc_uno_init(struct ifnet *ifp) struct usbnet * const un = ifp->if_softc; struct smsc_softc * const sc = usbnet_softc(un); - /* Cancel pending I/O */ - smsc_uno_stop(ifp, 1); - /* Reset the ethernet interface. */ smsc_reset(sc); From 5e67f8b22708da54733f0921bc4b759845943ddc Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 8 Jan 2022 03:29:54 +0000 Subject: [PATCH 67/77] url(4): Inline call to url_uno_stop -- alias for url_reset. --- sys/dev/usb/if_url.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index 880a47b781d2..fd64fb88a508 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -370,8 +370,7 @@ url_uno_init(struct ifnet *ifp) DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - /* Cancel pending I/O and free all TX/RX buffers */ - url_uno_stop(ifp, 1); + url_reset(un); eaddr = CLLADDR(ifp->if_sadl); for (i = 0; i < ETHER_ADDR_LEN; i++) From d5e2e64f4e7727f07424090bacf1979bdb9b40d9 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 8 Jan 2022 03:39:45 +0000 Subject: [PATCH 68/77] usbnet: Handle usbnet_set_link for drivers with no media detect. --- sys/dev/usb/if_cdce.c | 1 - sys/dev/usb/if_urndis.c | 1 - sys/dev/usb/usbnet.c | 7 +++++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c index 0b658fb0d2f0..e077091de930 100644 --- a/sys/dev/usb/if_cdce.c +++ b/sys/dev/usb/if_cdce.c @@ -262,7 +262,6 @@ cdce_uno_init(struct ifnet *ifp) int rv; rv = usbnet_init_rx_tx(un); - usbnet_set_link(un, rv == 0); return rv; } diff --git a/sys/dev/usb/if_urndis.c b/sys/dev/usb/if_urndis.c index 593d817e077b..3178bcfa53ce 100644 --- a/sys/dev/usb/if_urndis.c +++ b/sys/dev/usb/if_urndis.c @@ -878,7 +878,6 @@ urndis_uno_init(struct ifnet *ifp) if (error) return EIO; /* XXX */ error = usbnet_init_rx_tx(un); - usbnet_set_link(un, error == 0); return error; } diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 709aca405de4..48f54f1bb41d 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -904,6 +904,13 @@ out: usbnet_ep_close_pipes(un); } + /* + * For devices without any media autodetection, treat success + * here as an active link. + */ + if (un->un_ops->uno_statchg == NULL) + usbnet_set_link(un, error == 0); + usbnet_isowned_core(un); return error; From bd51fe79619585dd928c0c142be8448b05d189ad Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 8 Jan 2022 03:42:27 +0000 Subject: [PATCH 69/77] usbnet drivers: Simplify return of usbnet_init_rx_tx. --- sys/dev/usb/if_cdce.c | 5 +---- sys/dev/usb/if_udav.c | 6 ++---- sys/dev/usb/if_upl.c | 5 +---- sys/dev/usb/if_urndis.c | 3 +-- 4 files changed, 5 insertions(+), 14 deletions(-) diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c index e077091de930..13804e66b801 100644 --- a/sys/dev/usb/if_cdce.c +++ b/sys/dev/usb/if_cdce.c @@ -259,11 +259,8 @@ static int cdce_uno_init(struct ifnet *ifp) { struct usbnet *un = ifp->if_softc; - int rv; - rv = usbnet_init_rx_tx(un); - - return rv; + return usbnet_init_rx_tx(un); } static void diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index 21228ee725bd..63c3068b8720 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -502,11 +502,9 @@ udav_uno_init(struct ifnet *ifp) } if (usbnet_isdying(un)) - rc = EIO; - else - rc = usbnet_init_rx_tx(un); + return EIO; - return rc; + return usbnet_init_rx_tx(un); } static void diff --git a/sys/dev/usb/if_upl.c b/sys/dev/usb/if_upl.c index f90f644cf6b8..7f58fe587838 100644 --- a/sys/dev/usb/if_upl.c +++ b/sys/dev/usb/if_upl.c @@ -255,11 +255,8 @@ static int upl_uno_init(struct ifnet *ifp) { struct usbnet * const un = ifp->if_softc; - int rv; - rv = usbnet_init_rx_tx(un); - - return rv; + return usbnet_init_rx_tx(un); } static int diff --git a/sys/dev/usb/if_urndis.c b/sys/dev/usb/if_urndis.c index 3178bcfa53ce..5d7088b53008 100644 --- a/sys/dev/usb/if_urndis.c +++ b/sys/dev/usb/if_urndis.c @@ -877,9 +877,8 @@ urndis_uno_init(struct ifnet *ifp) error = urndis_init_un(ifp, un); if (error) return EIO; /* XXX */ - error = usbnet_init_rx_tx(un); - return error; + return usbnet_init_rx_tx(un); } static int From 6acfbdbcc4d05add99f460be4820076ceeb92c3c Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 8 Jan 2022 03:48:21 +0000 Subject: [PATCH 70/77] usbnet: Factor usbnet_init_rx_tx out into usbnet_if_init. Make it private; no need for drivers to call it any more. --- sys/dev/usb/if_aue.c | 2 +- sys/dev/usb/if_axe.c | 2 +- sys/dev/usb/if_axen.c | 2 +- sys/dev/usb/if_cdce.c | 3 +-- sys/dev/usb/if_cue.c | 2 +- sys/dev/usb/if_kue.c | 2 +- sys/dev/usb/if_mos.c | 2 +- sys/dev/usb/if_mue.c | 2 +- sys/dev/usb/if_smsc.c | 2 +- sys/dev/usb/if_udav.c | 2 +- sys/dev/usb/if_upl.c | 3 +-- sys/dev/usb/if_ure.c | 2 +- sys/dev/usb/if_url.c | 2 +- sys/dev/usb/if_urndis.c | 2 +- sys/dev/usb/usbnet.c | 9 +++++++-- sys/dev/usb/usbnet.h | 3 --- 16 files changed, 21 insertions(+), 21 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index 55f9d86c1dd5..bbfdbbc79a72 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -972,7 +972,7 @@ aue_uno_init(struct ifnet *ifp) AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_TX_ENB); AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_EP3_CLR); - return usbnet_init_rx_tx(un); + return 0; } static void diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index 3e3c4140e8fc..b137a3e88c1c 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -1286,7 +1286,7 @@ axe_uno_init(struct ifnet *ifp) axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); - return usbnet_init_rx_tx(un); + return 0; } static void diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index edc2f195642c..8dd209b8c393 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -896,7 +896,7 @@ axen_uno_init(struct ifnet *ifp) wval = htole16(rxmode); axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval); - return usbnet_init_rx_tx(un); + return 0; } static void diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c index 13804e66b801..14085b22400d 100644 --- a/sys/dev/usb/if_cdce.c +++ b/sys/dev/usb/if_cdce.c @@ -258,9 +258,8 @@ cdce_attach(device_t parent, device_t self, void *aux) static int cdce_uno_init(struct ifnet *ifp) { - struct usbnet *un = ifp->if_softc; - return usbnet_init_rx_tx(un); + return 0; } static void diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index 188f2fa173de..93e7a5c84f0e 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -654,7 +654,7 @@ cue_uno_init(struct ifnet *ifp) /* Program the LED operation. */ cue_csr_write_1(un, CUE_LEDCTL, CUE_LEDCTL_FOLLOW_LINK); - return usbnet_init_rx_tx(un); + return 0; } /* Stop and reset the adapter. */ diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index 3e63405dc650..1d003c34ad31 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -615,7 +615,7 @@ kue_uno_init(struct ifnet *ifp) #endif kue_setword(un, KUE_CMD_SET_URB_SIZE, 64); - return usbnet_init_rx_tx(un); + return 0; } #ifdef _MODULE diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index 6d5a4c6f5f4c..c777585b3654 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -750,7 +750,7 @@ mos_uno_init(struct ifnet *ifp) rxmode &= ~(MOS_CTL_SLEEP); mos_reg_write_1(un, MOS_CTL, rxmode); - return usbnet_init_rx_tx(un); + return 0; } void diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index bdb1a8c34a05..57558122af79 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -1244,7 +1244,7 @@ mue_uno_init(struct ifnet *ifp) /* Set MTU. */ mue_setmtu_locked(un); - return usbnet_init_rx_tx(un); + return 0; } static int diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index c1a5967ebd0b..63301688fc10 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -561,7 +561,7 @@ smsc_uno_init(struct ifnet *ifp) /* TCP/UDP checksum offload engines. */ smsc_setoe_locked(un); - return usbnet_init_rx_tx(un); + return 0; } static void diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index 63c3068b8720..69e988d91075 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -504,7 +504,7 @@ udav_uno_init(struct ifnet *ifp) if (usbnet_isdying(un)) return EIO; - return usbnet_init_rx_tx(un); + return 0; } static void diff --git a/sys/dev/usb/if_upl.c b/sys/dev/usb/if_upl.c index 7f58fe587838..b5eb8d3f05bd 100644 --- a/sys/dev/usb/if_upl.c +++ b/sys/dev/usb/if_upl.c @@ -254,9 +254,8 @@ upl_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) static int upl_uno_init(struct ifnet *ifp) { - struct usbnet * const un = ifp->if_softc; - return usbnet_init_rx_tx(un); + return 0; } static int diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index f39322237f33..67e9a7fb2afd 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -438,7 +438,7 @@ ure_uno_init(struct ifnet *ifp) ure_read_2(un, URE_PLA_MISC_1, URE_MCU_TYPE_PLA) & ~URE_RXDY_GATED_EN); - return usbnet_init_rx_tx(un); + return 0; } static void diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index fd64fb88a508..e59b1ef6c8f7 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -388,7 +388,7 @@ url_uno_init(struct ifnet *ifp) /* Enable RX and TX */ URL_SETBIT(un, URL_CR, URL_CR_TE | URL_CR_RE); - return usbnet_init_rx_tx(un); + return 0; } static void diff --git a/sys/dev/usb/if_urndis.c b/sys/dev/usb/if_urndis.c index 5d7088b53008..22cf550632f2 100644 --- a/sys/dev/usb/if_urndis.c +++ b/sys/dev/usb/if_urndis.c @@ -878,7 +878,7 @@ urndis_uno_init(struct ifnet *ifp) if (error) return EIO; /* XXX */ - return usbnet_init_rx_tx(un); + return 0; } static int diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 48f54f1bb41d..7af2ff020ff0 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -834,7 +834,7 @@ usbnet_ep_stop_pipes(struct usbnet * const un) return err; } -int +static int usbnet_init_rx_tx(struct usbnet * const un) { USBNETHIST_FUNC(); USBNETHIST_CALLED(); @@ -1290,7 +1290,12 @@ usbnet_if_init(struct ifnet *ifp) mutex_enter(&un->un_pri->unp_core_lock); error = uno_init(un, ifp); - mutex_exit(&un->un_pri->unp_core_lock); + if (error) + goto out; + error = usbnet_init_rx_tx(un); + if (error) + goto out; +out: mutex_exit(&un->un_pri->unp_core_lock); return error; } diff --git a/sys/dev/usb/usbnet.h b/sys/dev/usb/usbnet.h index bd5750bf3c5d..58164a330b96 100644 --- a/sys/dev/usb/usbnet.h +++ b/sys/dev/usb/usbnet.h @@ -307,10 +307,7 @@ bool usbnet_isdying(struct usbnet *); * usbnet_detach() frees the rx/tx chains * * Setup un_ed[] with valid end points before calling usbnet_attach(). - * Call usbnet_init_rx_tx() to initialise pipes, which will be open - * upon success. */ -int usbnet_init_rx_tx(struct usbnet * const); /* interrupt handling */ void usbnet_enqueue(struct usbnet * const, uint8_t *, size_t, int, From c535d38ed08f510272395368c25fccd96b168841 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 8 Jan 2022 03:52:30 +0000 Subject: [PATCH 71/77] usbnet: Omit empty uno_init functions. --- sys/dev/usb/if_cdce.c | 9 --------- sys/dev/usb/if_upl.c | 9 --------- sys/dev/usb/usbnet.c | 2 +- 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c index 14085b22400d..bf865f952709 100644 --- a/sys/dev/usb/if_cdce.c +++ b/sys/dev/usb/if_cdce.c @@ -82,12 +82,10 @@ static void cdce_uno_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); static unsigned cdce_uno_tx_prepare(struct usbnet *, struct mbuf *, struct usbnet_chain *); -static int cdce_uno_init(struct ifnet *); static const struct usbnet_ops cdce_ops = { .uno_tx_prepare = cdce_uno_tx_prepare, .uno_rx_loop = cdce_uno_rx_loop, - .uno_init = cdce_uno_init, }; static int @@ -255,13 +253,6 @@ cdce_attach(device_t parent, device_t self, void *aux) 0, NULL); } -static int -cdce_uno_init(struct ifnet *ifp) -{ - - return 0; -} - static void cdce_uno_rx_loop(struct usbnet * un, struct usbnet_chain *c, uint32_t total_len) { diff --git a/sys/dev/usb/if_upl.c b/sys/dev/usb/if_upl.c index b5eb8d3f05bd..ef20dd690e43 100644 --- a/sys/dev/usb/if_upl.c +++ b/sys/dev/usb/if_upl.c @@ -111,10 +111,8 @@ static void upl_uno_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); static unsigned upl_uno_tx_prepare(struct usbnet *, struct mbuf *, struct usbnet_chain *); static int upl_uno_ioctl(struct ifnet *, u_long, void *); -static int upl_uno_init(struct ifnet *); static const struct usbnet_ops upl_ops = { - .uno_init = upl_uno_init, .uno_tx_prepare = upl_uno_tx_prepare, .uno_rx_loop = upl_uno_rx_loop, .uno_ioctl = upl_uno_ioctl, @@ -251,13 +249,6 @@ upl_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) return total_len; } -static int -upl_uno_init(struct ifnet *ifp) -{ - - return 0; -} - static int upl_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) { diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 7af2ff020ff0..c68f4cbf7d75 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -205,7 +205,7 @@ static int uno_init(struct usbnet *un, struct ifnet *ifp) { KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); - return (*un->un_ops->uno_init)(ifp); + return un->un_ops->uno_init ? (*un->un_ops->uno_init)(ifp) : 0; } static int From d6a2d4fbd6e4ffc18d6b36b1f826b036a4402417 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 8 Jan 2022 04:09:04 +0000 Subject: [PATCH 72/77] usbnet: Omit needless detachcv name parameter to usbnet_attach. --- sys/dev/usb/if_aue.c | 2 +- sys/dev/usb/if_axe.c | 2 +- sys/dev/usb/if_axen.c | 2 +- sys/dev/usb/if_cdce.c | 2 +- sys/dev/usb/if_cue.c | 2 +- sys/dev/usb/if_kue.c | 2 +- sys/dev/usb/if_mos.c | 2 +- sys/dev/usb/if_mue.c | 2 +- sys/dev/usb/if_smsc.c | 2 +- sys/dev/usb/if_udav.c | 2 +- sys/dev/usb/if_upl.c | 2 +- sys/dev/usb/if_ure.c | 2 +- sys/dev/usb/if_url.c | 2 +- sys/dev/usb/if_urndis.c | 2 +- sys/dev/usb/usbnet.c | 3 +-- sys/dev/usb/usbnet.h | 2 +- 16 files changed, 16 insertions(+), 17 deletions(-) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index bbfdbbc79a72..e1598996c825 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -847,7 +847,7 @@ aue_attach(device_t parent, device_t self, void *aux) } /* First level attach. */ - usbnet_attach(un, "auedet"); + usbnet_attach(un); /* Reset the adapter and get station address from the EEPROM. */ aue_reset(sc); diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index b137a3e88c1c..5ee08ed64d4d 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -925,7 +925,7 @@ axe_attach(device_t parent, device_t self, void *aux) } /* Set these up now for axe_cmd(). */ - usbnet_attach(un, "axedet"); + usbnet_attach(un); /* We need the PHYID for init dance in some cases */ if (axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, &sc->axe_phyaddrs)) { diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index 8dd209b8c393..f0710f24fc77 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -650,7 +650,7 @@ axen_attach(device_t parent, device_t self, void *aux) } /* Set these up now for axen_cmd(). */ - usbnet_attach(un, "axendet"); + usbnet_attach(un); un->un_phyno = AXEN_PHY_ID; DPRINTF(("%s: phyno %d\n", device_xname(self), un->un_phyno)); diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c index bf865f952709..452be10fc77e 100644 --- a/sys/dev/usb/if_cdce.c +++ b/sys/dev/usb/if_cdce.c @@ -248,7 +248,7 @@ cdce_attach(device_t parent, device_t self, void *aux) un->un_eaddr[5] = (uint8_t)(device_unit(un->un_dev)); } - usbnet_attach(un, "cdcedet"); + usbnet_attach(un); usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 0, NULL); } diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index 93e7a5c84f0e..d6eaa2852123 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -525,7 +525,7 @@ cue_attach(device_t parent, device_t self, void *aux) } /* First level attach. */ - usbnet_attach(un, "cuedet"); + usbnet_attach(un); #if 0 /* Reset the adapter. */ diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index 1d003c34ad31..b34ac031559c 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -494,7 +494,7 @@ kue_attach(device_t parent, device_t self, void *aux) } /* First level attach, so kue_ctl() works. */ - usbnet_attach(un, "kuedet"); + usbnet_attach(un); /* Read ethernet descriptor */ err = kue_ctl(un, KUE_CTL_READ, KUE_CMD_GET_ETHER_DESCRIPTOR, diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index c777585b3654..a21c0557efb6 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -639,7 +639,7 @@ mos_attach(device_t parent, device_t self, void *aux) aprint_normal_dev(self, "MCS7832\n"); /* Set these up now for register access. */ - usbnet_attach(un, "mosdet"); + usbnet_attach(un); mos_chip_init(un); diff --git a/sys/dev/usb/if_mue.c b/sys/dev/usb/if_mue.c index 57558122af79..943fe926dc20 100644 --- a/sys/dev/usb/if_mue.c +++ b/sys/dev/usb/if_mue.c @@ -856,7 +856,7 @@ mue_attach(device_t parent, device_t self, void *aux) } /* Set these up now for mue_cmd(). */ - usbnet_attach(un, "muedet"); + usbnet_attach(un); un->un_phyno = 1; diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index 63301688fc10..717a6866e517 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -826,7 +826,7 @@ smsc_attach(device_t parent, device_t self, void *aux) } } - usbnet_attach(un, "smscdet"); + usbnet_attach(un); #ifdef notyet /* diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index 69e988d91075..9cf77d6dd869 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -236,7 +236,7 @@ udav_attach(device_t parent, device_t self, void *aux) /* Not supported yet. */ un->un_ed[USBNET_ENDPT_INTR] = 0; - usbnet_attach(un, "udavdet"); + usbnet_attach(un); // /* reset the adapter */ // udav_reset(un); diff --git a/sys/dev/usb/if_upl.c b/sys/dev/usb/if_upl.c index ef20dd690e43..770c3a244152 100644 --- a/sys/dev/usb/if_upl.c +++ b/sys/dev/usb/if_upl.c @@ -205,7 +205,7 @@ upl_attach(device_t parent, device_t self, void *aux) return; } - usbnet_attach(un, "upldet"); + usbnet_attach(un); /* Initialize interface info.*/ struct ifnet *ifp = usbnet_ifp(un); diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index 67e9a7fb2afd..713ad6317569 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -855,7 +855,7 @@ ure_attach(device_t parent, device_t self, void *aux) } /* Set these up now for ure_ctl(). */ - usbnet_attach(un, "uredet"); + usbnet_attach(un); un->un_phyno = 0; diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index e59b1ef6c8f7..56d6d350e0ca 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -240,7 +240,7 @@ url_attach(device_t parent, device_t self, void *aux) } /* Set these up now for url_mem(). */ - usbnet_attach(un, "urldet"); + usbnet_attach(un); /* reset the adapter */ url_reset(un); diff --git a/sys/dev/usb/if_urndis.c b/sys/dev/usb/if_urndis.c index 22cf550632f2..08a82be22c5d 100644 --- a/sys/dev/usb/if_urndis.c +++ b/sys/dev/usb/if_urndis.c @@ -1042,7 +1042,7 @@ urndis_attach(device_t parent, device_t self, void *aux) ifp->if_watchdog = urndis_watchdog; #endif - usbnet_attach(un, "urndisdet"); + usbnet_attach(un); struct ifnet *ifp = usbnet_ifp(un); urndis_init_un(ifp, un); diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index c68f4cbf7d75..c5951bf60b11 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1390,8 +1390,7 @@ usbnet_empty_eaddr(struct usbnet * const un) */ void -usbnet_attach(struct usbnet *un, - const char *detname) /* detach cv name */ +usbnet_attach(struct usbnet *un) { USBNETHIST_FUNC(); USBNETHIST_CALLED(); diff --git a/sys/dev/usb/usbnet.h b/sys/dev/usb/usbnet.h index 58164a330b96..2f09882c67a0 100644 --- a/sys/dev/usb/usbnet.h +++ b/sys/dev/usb/usbnet.h @@ -315,7 +315,7 @@ void usbnet_enqueue(struct usbnet * const, uint8_t *, size_t, int, void usbnet_input(struct usbnet * const, uint8_t *, size_t); /* autoconf */ -void usbnet_attach(struct usbnet *un, const char *); +void usbnet_attach(struct usbnet *); void usbnet_attach_ifp(struct usbnet *, unsigned, unsigned, const struct usbnet_mii *); int usbnet_detach(device_t, int); From 0863026d8346bcd4a009c7d4882d583bd03e77f3 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 9 Jan 2022 00:42:51 +0000 Subject: [PATCH 73/77] usbnet: Fix type of struct usbnet::un_ed according to plan. --- sys/dev/usb/usbnet.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sys/dev/usb/usbnet.h b/sys/dev/usb/usbnet.h index 2f09882c67a0..303178f0d6f1 100644 --- a/sys/dev/usb/usbnet.h +++ b/sys/dev/usb/usbnet.h @@ -262,11 +262,8 @@ struct usbnet { /* * This section should be filled in before calling * usbnet_attach_ifp(). - * - * XXX This should be of type "uByte". enum usbnet_ep - * is the index. Fix this in a kernel version bump. */ - enum usbnet_ep un_ed[USBNET_ENDPT_MAX]; + uByte un_ed[USBNET_ENDPT_MAX]; /* MII specific. Not used without MII. */ int un_phyno; From d0ac60169c1ee1431c0f487e71896b889b4ff0bd Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 9 Jan 2022 00:47:39 +0000 Subject: [PATCH 74/77] usbnet: On if_stop, abort xfers before resetting hardware. uno_stop is supposed to have exclusive access to the hardware; this ensures that any concurrent uno_rx_loop has completed before we enter uno_stop. --- sys/dev/usb/usbnet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index c5951bf60b11..1f57e11ea39e 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -1130,6 +1130,9 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER, &unp->unp_core_lock); + /* Stop transfers. */ + usbnet_ep_stop_pipes(un); + /* * Now that the software is quiescent, ask the driver to stop * the hardware. The driver's uno_stop routine now has @@ -1143,9 +1146,6 @@ usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) if (!usbnet_isdying(un)) uno_stop(un, ifp, disable); - /* Stop transfers. */ - usbnet_ep_stop_pipes(un); - /* Free RX/TX resources. */ usbnet_rx_list_fini(un); usbnet_tx_list_fini(un); From a77cdb3d9ea8de14c3994f61db496bab5f8ac330 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 9 Jan 2022 00:53:17 +0000 Subject: [PATCH 75/77] usbnet: Update some comments. --- sys/dev/usb/usbnet.h | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/sys/dev/usb/usbnet.h b/sys/dev/usb/usbnet.h index 303178f0d6f1..70f600b038f7 100644 --- a/sys/dev/usb/usbnet.h +++ b/sys/dev/usb/usbnet.h @@ -58,19 +58,12 @@ * cases), but provides a normal handler with callback to handle * ENETRESET conditions that should be sufficient for most users * - start uses usbnet transmit prepare callback (uno_tx_prepare) - * - interface init and stop have helper functions - * - device specific init should use usbnet_init_rx_tx() to open pipes - * to the device and setup the rx/tx chains for use after any device - * specific setup - * - usbnet_stop() must be called with the un_lock held, and will - * call the device-specific usbnet stop callback, which enables the - * standard init calls stop idiom. * - interrupt handling: - * - for rx, usbnet_init_rx_tx() will enable the receive pipes and + * - for rx, usbnet will enable the receive pipes and * call the rx_loop callback to handle device specific processing of * packets, which can use usbnet_enqueue() to provide data to the * higher layers - * - for tx, usbnet_start (if_start) will pull entries out of the + * - for tx, usbnet will pull entries out of the * transmit queue and use the transmit prepare callback (uno_tx_prepare) * for the given mbuf. the usb callback will use usbnet_txeof() for * the transmit completion function (internal to usbnet) @@ -175,8 +168,7 @@ typedef void (*usbnet_intr_cb)(struct usbnet *, usbd_status); * Note that the IFNET_LOCK **may not be held** for the ioctl commands * SIOCADDMULTI/SIOCDELMULTI. These commands are only passed * explicitly to uno_override_ioctl; for all other devices, they are - * handled inside usbnet by scheduling a task to asynchronously call - * uno_mcast with IFNET_LOCK held. + * handled by uno_mcast (also without IFNET_LOCK). */ struct usbnet_ops { usbnet_stop_cb uno_stop; /* C */ @@ -297,10 +289,20 @@ bool usbnet_isdying(struct usbnet *); /* * Endpoint / rx/tx chain management: * - * usbnet_attach() initialises usbnet and allocates rx and tx chains - * usbnet_init_rx_tx() open pipes, initialises the rx/tx chains for use - * usbnet_stop() stops pipes, cleans (not frees) rx/tx chains, locked - * version assumes un_lock is held + * 1. usbnet_attach() initialises usbnet and allocates rx and tx chains + * + * 2. On if_init, usbnet: + * - calls uno_init to initialize hardware + * - open pipes + * - initialises the rx/tx chains for use + * - calls uno_mcast to program hardware multicast filter + * + * 3. On if_stop, usbnet: + * - stops pipes + * - calls uno_stop to stop hardware (unless we're detaching anyway) + * - cleans (not frees) rx/tx chains + * - closes pipes + * * usbnet_detach() frees the rx/tx chains * * Setup un_ed[] with valid end points before calling usbnet_attach(). From b092311746468b62bb0bced0374d2baafbcb52c8 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 20 Jan 2022 22:41:54 +0000 Subject: [PATCH 76/77] urndis(4): Simplify circuitous initialization logic. --- sys/dev/usb/if_urndis.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/sys/dev/usb/if_urndis.c b/sys/dev/usb/if_urndis.c index 08a82be22c5d..ac70280bff8d 100644 --- a/sys/dev/usb/if_urndis.c +++ b/sys/dev/usb/if_urndis.c @@ -72,8 +72,6 @@ static void urndis_uno_rx_loop(struct usbnet *, struct usbnet_chain *, static unsigned urndis_uno_tx_prepare(struct usbnet *, struct mbuf *, struct usbnet_chain *); -static int urndis_init_un(struct ifnet *, struct usbnet *); - static uint32_t urndis_ctrl_handle_init(struct usbnet *, const struct rndis_comp_hdr *); static uint32_t urndis_ctrl_handle_query(struct usbnet *, @@ -854,29 +852,15 @@ urndis_watchdog(struct ifnet *ifp) } #endif -static int -urndis_init_un(struct ifnet *ifp, struct usbnet *un) -{ - int err; - - err = urndis_ctrl_init(un); - if (err != RNDIS_STATUS_SUCCESS) - return EIO; - - return err; -} - static int urndis_uno_init(struct ifnet *ifp) { struct usbnet *un = ifp->if_softc; - int error; KASSERT(IFNET_LOCKED(ifp)); - error = urndis_init_un(ifp, un); - if (error) - return EIO; /* XXX */ + if (urndis_ctrl_init(un) != RNDIS_STATUS_SUCCESS) + return EIO; return 0; } @@ -1044,8 +1028,11 @@ urndis_attach(device_t parent, device_t self, void *aux) usbnet_attach(un); - struct ifnet *ifp = usbnet_ifp(un); - urndis_init_un(ifp, un); + if (urndis_ctrl_init(un) != RNDIS_STATUS_SUCCESS) { + aprint_error("%s: unable to initialize hardware\n", + DEVNAME(un)); + return; + } if (urndis_ctrl_query(un, OID_802_3_PERMANENT_ADDRESS, NULL, 0, &buf, &bufsz) != RNDIS_STATUS_SUCCESS) { From cd9739162e2f16ef7764e75d048fa70e6207385c Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 20 Jan 2022 22:03:56 +0000 Subject: [PATCH 77/77] usbnet(9): Update man page. --- share/man/man9/usbnet.9 | 370 +++++++++++++++------------------------- 1 file changed, 141 insertions(+), 229 deletions(-) diff --git a/share/man/man9/usbnet.9 b/share/man/man9/usbnet.9 index b839a5d620e5..2da4c7b3e06f 100644 --- a/share/man/man9/usbnet.9 +++ b/share/man/man9/usbnet.9 @@ -35,8 +35,6 @@ .Ss Functions offered by usbnet.h .Ft void .Fn usbnet_set_link "struct usbnet *un" "bool link" -.Ft void -.Fn usbnet_set_dying "struct usbnet *un" "bool dying" .Ft struct ifnet * .Fn usbnet_ifp "struct usbnet *un" .Ft struct ethercom * @@ -52,55 +50,17 @@ .Ft bool .Fn usbnet_isdying "struct usbnet *un" .Ft void -.Fn usbnet_lock_core "struct usbnet *un" -.Ft void -.Fn usbnet_unlock_core "struct usbnet *un" -.Ft kmutex_t * -.Fn usbnet_mutex_core "struct usbnet *un" -.Ft void -.Fn usbnet_isowned_core "struct usbnet *un" -.Ft void -.Fn usbnet_lock_rx "struct usbnet *un" -.Ft void -.Fn usbnet_unlock_rx "struct usbnet *un" -.Ft kmutex_t * -.Fn usbnet_mutex_rx "struct usbnet *un" -.Ft void -.Fn usbnet_isowned_rx "struct usbnet *un" -.Ft void -.Fn usbnet_lock_tx "struct usbnet *un" -.Ft void -.Fn usbnet_unlock_tx "struct usbnet *un" -.Ft kmutex_t * -.Fn usbnet_mutex_tx "struct usbnet *un" -.Ft void -.Fn usbnet_isowned_tx "struct usbnet *un" -.Ft int -.Fn usbnet_init_rx_tx "struct usbnet *un" "unsigned rxflags" "unsigned txflags" -.Ft int -.Fn usbnet_miibus_readreg "device_t dev" "int phy" "int reg" "uint16_t *val" -.Ft int -.Fn usbnet_miibus_writereg "device_t dev" "int phy" "int reg" "uint16_t val" -.Ft void -.Fn usbnet_miibus_statchg "struct ifnet *" -.Ft void -.Fn usbnet_busy "struct usbnet *un" -.Ft void -.Fn usbnet_unbusy "struct usbnet *un" -.Ft void .Fn usbnet_enqueue "struct usbnet *un" "uint8_t *buf" "size_t buflen" "int csum_flags" "uint32_t csum_data" "int mbuf_flags" .Ft void .Fn usbnet_input "struct usbnet *un" "uint8_t *buf" "size_t buflen" .Ft void -.Fn usbnet_attach "struct usbnet *un" "const char *detname" +.Fn usbnet_attach "struct usbnet *un" .Ft void .Fn usbnet_attach_ifp "struct usbnet *un" "unsigned if_flags" "unsigned if_extflags" "const struct usbnet_mii *unm" .Ft int .Fn usbnet_detach "device_t dev" "int flags" .Ft int .Fn usbnet_activate "device_t dev" "devact_t act" -.Ft void -.Fn usbnet_stop "struct usbnet *un" "struct ifnet *ifp" "int disable" .Sh DESCRIPTION The .Nm @@ -160,42 +120,66 @@ framework itself. The device activate function should be set to .Fn usbnet_activate . .Pp -To manage all Rx and Tx chains the -.Dq uno_init -callback of -.Va struct usbnet_ops -should perform any device specific initialization and then call -.Fn usbnet_init_rx_tx -which will allocate chains, set up and open pipes, and start the -Rx transfers so that packets can arrived. -These allocations and pipes can be closed and destroyed by calling -.Fn usbnet_stop . -Both of -.Fn usbnet_init_rx_tx -and -.Fn usbnet_stop -must be called with the +When bringing an interface up from +.Xr if_init 9 , +which happens under +.Xr IFNET_LOCK 9 , .Nm -lock held, see -.Fn usbnet_lock -and -.Fn usbnet_unlock . +will: +.Bl -enum +.It +call +.Dq uno_init +to initialize the hardware for sending and receiving packets, +.It +open the USB pipes, +.It +allocate Rx and Tx buffers for transfers, +.It +call +.Dq uno_mcast +to initially program the hardware multicast filter, and finally +.It +start the Rx transfers so packets can be received. +.El +.Pp See the .Sx RECEIVE AND SEND section for details on using the chains. .Pp -The interface init, ioctl, start, and stop, routines are handled by the -framework with callbacks for device-specific handling. -For interface init (i.e., when bringing the interface up), the -.Dq uno_init -callback should perform any device specific initialization and then call -.Fn usbnet_init_rx_tx -to finalize Rx and Tx queue initialization. -For interface ioctl, most of the handling is in the framework and the -optional +When bringing an interface down, +.Nm +will: +.Bl -enum +.It +abort the USB pipes, +.It +call +.Dq uno_stop +to stop the hardware from receiving packets (unless the device is +detaching), +.It +free Rx and Tx buffers for transfers, and +.It +close the USB pipes. +.El +.Pp +For interface ioctl, most of the handling is in the framework. +While the interface is running, the optional +.Dq uno_mcast +callback is invoked after handling the +.Dv SIOCADDMULTI +and +.Dv SIOCDELMULTI +ioctl commands to update the hardware's multicast filter from the +.Xr ethersubr 9 +lists. +The optional .Dq uno_ioctl -callback should be used to program special settings -like multicast filters or offload handling. +callback, which is invoked under +.Xr IFNET_LOCK 9 , +can be used to program special settings like offload handling. +.Pp If ioctl handling requires capturing device-specific ioctls then the .Dq uno_override_ioctl callback may be used instead to replace the framework's @@ -203,26 +187,15 @@ ioctl handler completely (i.e., the replacement should call any generic ioctl handlers such as .Fn ether_ioctl as required.) -For interface start, the +For sending packets, the .Dq uno_tx_prepare callback must be used to convert an mbuf into a chain buffer ready for transmission. -For interface stop, there is an optional -.Dq uno_stop -callback to turn off any chipset specific values if required. .Pp For devices requiring MII handling there are callbacks for reading and writing registers, and for status change events. -The framework serializes MII access with the core lock, which will be -held when calling these functions, and this lock should be used by -internal code that also requires serialized access to registers with the -.Fn usbnet_lock_core -and -.Fn usbnet_unlock_core -functions. -The MII callbacks handle device detach events safely; a reference count -is taken and released around calls to the callbacks as the MII callbacks -usually block. +Access to all the MII functions is serialized by +.Nm . .Pp As receive must handle the case of multiple packets in one buffer, the support is split between the driver and the framework. @@ -245,101 +218,32 @@ Set the link status for this .Fa un to .Fa link . -.It Fn usbnet_set_dying un dying -Set the dying status for this -.Fa un -to -.Fa dying . .It Fn usbnet_ifp un Returns pointer to this -.Fa un's +.Fa un Ns 's .Va struct ifnet . .It Fn usbnet_ec un Returns pointer to this -.Fa un's +.Fa un Ns 's .Va struct ethercom . .It Fn usbnet_mii un Returns pointer to this -.Fa un's +.Fa un Ns 's .Va struct mii_data . .It Fn usbnet_rndsrc un Returns pointer to this -.Fa un's +.Fa un Ns 's .Va krndsource_t . .It Fn usbnet_softc un Returns pointer to this -.Fa un's +.Fa un Ns 's device softc. .It Fn usbnet_havelink un Returns true if link is active. .It Fn usbnet_isdying un Returns true if device is dying (has been pulled or deactivated, -pending detach.) -.El -.Pp -Reference counting functions for -.Fa struct usbnet : -.Bl -tag -width 4n -.It Fn usbnet_busy un -Increases the reference count on the driver instance, preventing -detach from occurring while the driver is blocked accessing the -device. -Must be called with the core lock held. -.It Fn usbnet_unbusy un -Decreases the reference count on the driver instance. -Once the final reference has been dropped, if a detach event -is pending, it is allowed to proceed. -Must be called with the core lock held. -.El -.Pp -Lock handling functions for -.Fa struct usbnet : -.Pp -.Bl -tag -width 4n -compact -.It Fn usbnet_lock_core un -.It Fn usbnet_unlock_core un -.It Fn usbnet_isowned_core un -.It Fn usbnet_lock_rx un -.It Fn usbnet_unlock_rx un -.It Fn usbnet_isowned_rx un -.It Fn usbnet_lock_tx un -.It Fn usbnet_unlock_tx un -.It Fn usbnet_isowned_tx un -These groups of three functions provide methods to lock, -unlock, and assert ownership of one of the three locks provided by -.Nm . -The three locks are the -.Dq core -lock, the -.Dq Tx -lock, and the -.Dq Rx -lock. -.El -.Pp -MII access functions for -.Fa struct usbnet : -.Bl -tag -width 4n -.It Fn usbnet_mii_readreg dev phy reg valp -Read register -.Fa reg -on PHY number -.Fa phy -and return the value in -.Fa valp . -Called with the core lock held. -.It Fn usbnet_mii_writereg dev phy reg val -Write register -.Fa reg -on PHY number -.Fa phy -with -.Fa val . -Called with the core lock held. -.It Fn usbnet_mii_statchg ifp -Trigger a status change update for interface -.Fa ifp . -Called with the core lock held. +pending detach). +This should be used only to abort timeout loops early. .El .Pp Buffer enqueue handling for @@ -362,7 +266,7 @@ Enqueue buffer .Fa buf for length .Fa buflen -with higher layers +with higher layers. .El .Pp Autoconfiguration handling for @@ -371,13 +275,14 @@ See the .Sx AUTOCONFIGURATION section for more details about these functions. .Bl -tag -width 4n -.It Fn usbnet_attach un detachname +.It Fn usbnet_attach un Initial stage attach of a usb network device. -The -.Fa detachname -will be used while waiting for final references to drain when detaching. +Performs internal initialization and memory allocation only \(em +nothing is published yet. .It Fn usbnet_attach_ifp un if_flags if_extflags unm Final stage attach of usb network device. +Publishes the network interface to the rest of the system. +.Pp If the passed in .Fa unm is @@ -387,7 +292,7 @@ provided in the .Fa struct usbnet_mii structure, which has these members passed to .Fn mii_attach : -.Bl -tag -width 4n +.Bl -tag -width "un_mii_capmask" .It un_mii_flags Flags. .It un_mii_capmask @@ -410,12 +315,15 @@ and will be or-ed into the interface flags and extflags. .It Fn usbnet_detach dev flags Device detach. -Usable as actual device method. +Stops all activity and frees memory. +Usable as +.Xr driver 9 +detach method. .It Fn usbnet_activate dev act Device activate (deactivate) method. -Usable as actual device method. -.It Fn usbnet_stop un ifp disable -Interface stop routine. +Usable as +.Xr driver 9 +activate method. .El .Sh AUTOCONFIGURATION The framework expects the usbnet structure to have these members @@ -440,66 +348,102 @@ Points to a structure which contains these members: .Bl -tag -width 4n .It Ft void Fn (*uno_stop) "struct ifnet *ifp" "int disable" -Stop interface +Stop hardware activity .Pq optional . -Called with the core lock held and with a busy reference. +Called under +.Xr IFNET_LOCK 9 +when bringing the interface down, except when the device is detaching. .It Ft int Fn (*uno_ioctl) "struct ifnet *ifp" "u_long cmd" "void *data" -Simple ioctl callback +Handle driver-specific ioctls .Pq optional . -May be called with the ifnet lock held. +Called under +.Xr IFNET_LOCK 9 . +.It Ft void Fn (*uno_mcast) "struct ifnet *" +Program hardware multicast filters from +.Xr ethersubr 9 +lists +.Pq optional . +Called between, and not during, +.Dq uno_init +and +.Dq uno_stop . .It Ft int Fn (*uno_override_ioctl) "struct ifnet *ifp" "u_long cmd" "void *data" -Full ioctl callback +Handle all ioctls, including standard ethernet ioctls normally handled +internally by +.Nm .Pq optional . -May be called with the ifnet lock held. +May or may not be called under +.Xr IFNET_LOCK 9 . .It Ft int Fn (*uno_init) "struct ifnet *ifp" -Initialize (bring up) interface. +Initialize hardware activity. Required. -Called with the ifnet lock held. -Must call -.Fn usbnet_rx_tx_init . +Called under +.Xr IFNET_LOCK 9 +when bringing the interface up. .It Ft int Fn (*uno_read_reg) "struct usbnet *un" "int phy" "int reg" "uint16_t *val" Read MII register. Required with MII. -Called with the core lock held and with a busy reference. +Serialized with other MII functions, and with +.Dq uno_init +and +.Dq uno_stop . .It Ft int Fn (*uno_write_reg) "struct usbnet *un" "int phy" "int reg" "uint16_t val" Write MII register. Required with MII. -Called with the core lock held and with a busy reference. +Serialized with other MII functions, and with +.Dq uno_init +and +.Dq uno_stop . .It Ft usbd_status Fn (*uno_statchg) "struct ifnet *ifp" Handle MII status change. Required with MII. -Called with the core lock held and with a busy reference. +Serialized with other MII functions, and with +.Dq uno_init +and +.Dq uno_stop . .It Ft unsigned Fn (*uno_tx_prepare) "struct usbnet *un" "struct mbuf *m" "struct usbnet_chain *c" Prepare an mbuf for transmit. Required. -Called with the Tx lock held. +Called sequentially between, and not during, +.Dq uno_init . +and +.Dq uno_stop . .It Ft void Fn (*uno_rx_loop) "struct usbnet *un" "struct usbnet_chain *c" "uint32_t total_len" Prepare one or more chain for enqueue. Required. -Called with the Rx lock held. +Called sequentially between, and not during, +.Dq uno_init +and +.Dq uno_stop . .It Ft void Fn (*uno_intr) "struct usbnet *un" "usbd_status status" Process periodic interrupt .Pq optional . -Called with no locks held. +Called sequentially between, and not during, +.Dq uno_init +and +.Dq uno_stop . .It Ft void Fn (*uno_tick) "struct usbnet *un" Called every second with USB task thread context .Pq optional . -Called with no locks held, but a busy reference is maintained across this call. +Called sequentially between, and not during, +.Dq uno_init +and +.Dq uno_stop . .El .It un_intr Points to a .Va struct usbnet_intr structure which should have these members set: .Bl -tag -width 4n -.It uni_intr_buf +.It uni_buf If .Pf non- Dv NULL , points to a buffer passed to .Fn usbd_open_pipe_intr in the device init callback, along with the size and interval. -.It uni_intr_bufsz +.It uni_bufsz Size of interrupt pipe buffer. -.It uni_intr_interval +.It uni_interval Frequency of the interrupt in milliseconds. .El .It un_ed @@ -591,8 +535,6 @@ The optional .Fn uno_stop callback performs device-specific operations to shutdown the transmit or receive handling. -.Fn uno_stop -will be called with the usbnet lock held. .Pp The .Fn uno_init @@ -606,7 +548,7 @@ what is typically a device-specific method. .Pp The .Fn uno_rx_loop -callback converts the provided +callback, called sequentially, converts the provided .Va usbnet_chain data and length into a series (one or more) of packets that are enqueued with the higher layers using either @@ -615,15 +557,12 @@ enqueued with the higher layers using either .Fn usbnet_input for devices that use .Fn if_input -(this currently relies upon the +. +(This currently relies upon the .Va struct ifnet having the .Dq _if_input member set as well, which is true for current consumers.) -The Rx lock will be held during this call, see -.Fn usbnet_lock_rx -and -.Fn usbnet_unlock_rx . .Pp The .Fn uno_tx_prepare @@ -637,11 +576,7 @@ more than the chain buffer size, as set in the .Va usbnet .Dq un_tx_bufsz member. -This callback is only called once per packet. -The Tx lock will be held during this call, see -.Fn usbnet_lock_tx -and -.Fn usbnet_unlock_tx . +This callback is only called once per packet, sequentially. .Pp The .Fa struct usbnet_chain @@ -663,6 +598,7 @@ must be provided: Read an MII register for a particular PHY. Returns standard .Xr errno 2 . +Must initialize the result even on failure. .It uno_write_reg Write an MII register for a particular PHY. Returns standard @@ -670,12 +606,6 @@ Returns standard .It uno_statchg Handle a status change event for this interface. .El -.Pp -The read and write callbacks are called with the core lock held. -See -.Fn usbnet_lock_mii -and -.Fn usbnet_unlock_mii . .Sh INTERRUPT PIPE The interrupt specific callback, .Dq uno_intr , @@ -735,8 +665,7 @@ interface, and task and callout structures (both these probably go away entirely) and all the associated watchdog handling, timevals, list size, buffer size and xfer flags for both Rx, and Tx, and interrupt notices, interface flags, device link, -PHY number, chain data, locks including Rx, Tx, MII, and the -base softc lock. +PHY number, chain data, locks including Rx, Tx, and MII. There is a driver-only .Dq un_flags in the @@ -798,28 +727,11 @@ The device routine is replaced with a simple call that turns off the device-specific transmitter and receiver if necessary, as the framework handles pipes and transfers and buffers. -.It Device locking -The -.Nm -framework provides three locks for the system: core lock, -receive lock, and transmit lock. -The normal locking order -for these locks is ifnet lock -> usbnet core lock -> usbnet rxlock -> usbnet -txlock, or, ifnet lock -> usbnet core lock. -Also note that the core lock may be taken when the ifnet lock is not -held. .It MII handling For devices with MII support the three normal callbacks .Pq read, write, and status change must be converted to .Va usbnet . -These functions are called with the core lock is held -.Po -see -.Dq Fn usbnet_isowned_core -.Pc , -and with a busy reference held and do not require any checking for running, -or up, or dying devices. Local .Dq link variables need to be replaced with accesses to