diff -r 05a88544f238 sys/dev/usb/if_urtwn.c --- a/sys/dev/usb/if_urtwn.c Wed Aug 06 17:25:38 2025 +0000 +++ b/sys/dev/usb/if_urtwn.c Sat Aug 09 04:59:27 2025 +1000 @@ -2659,6 +2659,7 @@ urtwn_txeof(struct usbd_xfer *xfer, void urtwn_put_tx_data(sc, data); s = splnet(); + sc->sc_numxfers--; sc->tx_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; @@ -2697,6 +2698,12 @@ urtwn_tx(struct urtwn_softc *sc, struct URTWNHIST_FUNC(); URTWNHIST_CALLED(); + mutex_enter(&sc->sc_tx_mtx); + if (sc->sc_numxfers > (sc->tx_npipe - 1)) { + mutex_exit(&sc->sc_tx_mtx); + return EAGAIN; + } + wh = mtod(m, struct ieee80211_frame *); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; txd_len = sizeof(*txd); @@ -2707,6 +2714,7 @@ urtwn_tx(struct urtwn_softc *sc, struct if (wh->i_fc[1] & IEEE80211_FC1_WEP) { k = ieee80211_crypto_encap(ic, ni, m); if (k == NULL) { + mutex_exit(&sc->sc_tx_mtx); urtwn_put_tx_data(sc, data); m_free(m); return ENOBUFS; @@ -2874,14 +2882,17 @@ urtwn_tx(struct urtwn_softc *sc, struct usbd_setup_xfer(data->xfer, data, data->buf, xferlen, USBD_FORCE_SHORT_XFER, URTWN_TX_TIMEOUT, urtwn_txeof); + sc->sc_numxfers++; error = usbd_transfer(data->xfer); if (__predict_false(error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS)) { splx(s); DPRINTFN(DBG_TX, "transfer failed %jd", error, 0, 0, 0); + mutex_exit(&sc->sc_tx_mtx); return error; } splx(s); + mutex_exit(&sc->sc_tx_mtx); return 0; } diff -r 05a88544f238 sys/dev/usb/if_urtwnvar.h --- a/sys/dev/usb/if_urtwnvar.h Wed Aug 06 17:25:38 2025 +0000 +++ b/sys/dev/usb/if_urtwnvar.h Sat Aug 09 04:59:27 2025 +1000 @@ -140,6 +140,7 @@ struct urtwn_softc { int rx_npipe; struct usbd_pipe * tx_pipe[R92C_MAX_EPOUT]; int tx_npipe; + int sc_numxfers; int ac2idx[WME_NUM_AC]; u_int chip;