diff -r d950fa65e8d8 sys/dev/usb/if_urtwn.c --- a/sys/dev/usb/if_urtwn.c Wed Aug 13 06:47:28 2025 +0000 +++ b/sys/dev/usb/if_urtwn.c Thu Aug 21 02:14:34 2025 +1000 @@ -248,6 +248,8 @@ static int urtwn_alloc_rx_list(struct ur static void urtwn_free_rx_list(struct urtwn_softc *); static int urtwn_alloc_tx_list(struct urtwn_softc *); static void urtwn_free_tx_list(struct urtwn_softc *); +static int urtwn_alloc_dummy_list(struct urtwn_softc *); +static void urtwn_free_dummy_list(struct urtwn_softc *); static void urtwn_task(void *); static void urtwn_do_async(struct urtwn_softc *, void (*)(struct urtwn_softc *, void *), void *, int); @@ -302,10 +304,13 @@ static int8_t urtwn_r88e_get_rssi(struct static void urtwn_rx_frame(struct urtwn_softc *, uint8_t *, int); static void urtwn_rxeof(struct usbd_xfer *, void *, usbd_status); static void urtwn_txeof(struct usbd_xfer *, void *, usbd_status); +static void urtwn_dummytxeof(struct usbd_xfer *, void *, usbd_status); static int urtwn_tx(struct urtwn_softc *, struct mbuf *, struct ieee80211_node *, struct urtwn_tx_data *); static struct urtwn_tx_data * urtwn_get_tx_data(struct urtwn_softc *, size_t); +static struct urtwn_tx_data * + urtwn_get_dummy_data(struct urtwn_softc *, size_t); static void urtwn_start(struct ifnet *); static void urtwn_watchdog(struct ifnet *); static int urtwn_ioctl(struct ifnet *, u_long, void *); @@ -798,6 +803,68 @@ urtwn_free_rx_list(struct urtwn_softc *s } static int __noinline +urtwn_alloc_dummy_list(struct urtwn_softc *sc) +{ + struct urtwn_tx_data *data; + size_t i; + int error = 0; + + URTWNHIST_FUNC(); URTWNHIST_CALLED(); + + mutex_enter(&sc->sc_tx_mtx); + for (size_t j = 0; j < sc->tx_npipe; j++) { + TAILQ_INIT(&sc->dummy_free_list[j]); + for (i = 0; i < URTWN_TX_LIST_COUNT; i++) { + data = &sc->dummy_data[j][i]; + + data->sc = sc; /* Backpointer for callbacks. */ + data->pidx = j; + + error = usbd_create_xfer(sc->tx_pipe[j], + 4, USBD_FORCE_SHORT_XFER, 0, + &data->xfer); + if (error) { + aprint_error_dev(sc->sc_dev, + "could not allocate xfer\n"); + goto fail; + } + + data->buf = usbd_get_buffer(data->xfer); + + /* Append this Tx buffer to our free list. */ + TAILQ_INSERT_TAIL(&sc->dummy_free_list[j], data, next); + } + } + mutex_exit(&sc->sc_tx_mtx); + return 0; + + fail: + urtwn_free_dummy_list(sc); + mutex_exit(&sc->sc_tx_mtx); + return error; +} + +static void +urtwn_free_dummy_list(struct urtwn_softc *sc) +{ + struct usbd_xfer *xfer; + size_t i; + + URTWNHIST_FUNC(); URTWNHIST_CALLED(); + + /* NB: Caller must abort pipe first. */ + for (size_t j = 0; j < sc->tx_npipe; j++) { + for (i = 0; i < URTWN_TX_LIST_COUNT; i++) { + CTASSERT(sizeof(xfer) == sizeof(void *)); + xfer = atomic_swap_ptr(&sc->dummy_data[j][i].xfer, + NULL); + if (xfer != NULL) + usbd_destroy_xfer(xfer); + } + } +} + +static int __noinline urtwn_alloc_tx_list(struct urtwn_softc *sc) { struct urtwn_tx_data *data; @@ -2634,6 +2701,17 @@ urtwn_rxeof(struct usbd_xfer *xfer, void } static void +urtwn_put_dummy_data(struct urtwn_softc *sc, struct urtwn_tx_data *data) +{ + size_t pidx = data->pidx; + + mutex_enter(&sc->sc_tx_mtx); + /* Put this Tx buffer back to our free list. */ + TAILQ_INSERT_TAIL(&sc->dummy_free_list[pidx], data, next); + mutex_exit(&sc->sc_tx_mtx); +} + +static void urtwn_put_tx_data(struct urtwn_softc *sc, struct urtwn_tx_data *data) { size_t pidx = data->pidx; @@ -2645,6 +2723,15 @@ urtwn_put_tx_data(struct urtwn_softc *sc } static void +urtwn_dummytxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) +{ + struct urtwn_tx_data *data = priv; + struct urtwn_softc *sc = data->sc; + + urtwn_put_dummy_data(sc, data); +} + +static void urtwn_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) { struct urtwn_tx_data *data = priv; @@ -2657,7 +2744,6 @@ urtwn_txeof(struct usbd_xfer *xfer, void DPRINTFN(DBG_TX, "status=%jd", status, 0, 0, 0); urtwn_put_tx_data(sc, data); - s = splnet(); sc->tx_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; @@ -2672,10 +2758,26 @@ urtwn_txeof(struct usbd_xfer *xfer, void usbd_errstr(status)); if_statinc(ifp, if_oerrors); } + splx(s); return; } + + struct urtwn_tx_data *dummy = NULL; + dummy = urtwn_get_dummy_data(sc, pidx); + if (dummy == NULL) { + printf("DUMMMY NULL!!!\n"); + goto done; + } + + *dummy->buf = 0; + usbd_setup_xfer(dummy->xfer, dummy, NULL, 0, + USBD_FORCE_SHORT_XFER | USBD_SYNCHRONOUS_SIG, URTWN_TX_TIMEOUT, + urtwn_dummytxeof); + usbd_transfer(dummy->xfer); + +done: if_statinc(ifp, if_opackets); urtwn_start(ifp); splx(s); @@ -2886,6 +2988,21 @@ urtwn_tx(struct urtwn_softc *sc, struct } struct urtwn_tx_data * +urtwn_get_dummy_data(struct urtwn_softc *sc, size_t pidx) +{ + struct urtwn_tx_data *data = NULL; + + mutex_enter(&sc->sc_tx_mtx); + if (!TAILQ_EMPTY(&sc->dummy_free_list[pidx])) { + data = TAILQ_FIRST(&sc->dummy_free_list[pidx]); + TAILQ_REMOVE(&sc->dummy_free_list[pidx], data, next); + } + mutex_exit(&sc->sc_tx_mtx); + + return data; +} + +struct urtwn_tx_data * urtwn_get_tx_data(struct urtwn_softc *sc, size_t pidx) { struct urtwn_tx_data *data = NULL; @@ -3002,6 +3119,7 @@ urtwn_start(struct ifnet *ifp) device_printf(sc->sc_dev, "unable to transmit packet\n"); if_statinc(ifp, if_oerrors); + urtwn_put_tx_data(sc, data); continue; } m_freem(m); @@ -3367,7 +3485,7 @@ urtwn_llt_init(struct urtwn_softc *sc) if (sc->chip & URTWN_CHIP_88E) pktbuf_count = R88E_TXPKTBUF_COUNT; else if (sc->chip & URTWN_CHIP_92EU) - pktbuf_count = R88E_TXPKTBUF_COUNT; + pktbuf_count = R92E_TXPKTBUF_COUNT; else pktbuf_count = R92C_TXPKTBUF_COUNT; @@ -4825,6 +4943,13 @@ urtwn_init(struct ifnet *ifp) goto fail; } + error = urtwn_alloc_dummy_list(sc); + if (error != 0) { + aprint_error_dev(sc->sc_dev, + "could not allocate dummy buffers\n"); + goto fail; + } + /* Power on adapter. */ error = urtwn_power_on(sc); if (error != 0) @@ -5091,6 +5216,7 @@ urtwn_stop(struct ifnet *ifp, int disabl /* Free Tx/Rx buffers. */ urtwn_free_tx_list(sc); + urtwn_free_dummy_list(sc); urtwn_free_rx_list(sc); sc->sc_running = false; diff -r d950fa65e8d8 sys/dev/usb/if_urtwnvar.h --- a/sys/dev/usb/if_urtwnvar.h Wed Aug 13 06:47:28 2025 +0000 +++ b/sys/dev/usb/if_urtwnvar.h Thu Aug 21 02:14:34 2025 +1000 @@ -23,7 +23,7 @@ * Driver definitions. */ #define URTWN_RX_LIST_COUNT 1 -#define URTWN_TX_LIST_COUNT 8 +#define URTWN_TX_LIST_COUNT 1 #define URTWN_HOST_CMD_RING_COUNT 32 @@ -172,8 +172,10 @@ struct urtwn_softc { int fwcur; struct urtwn_rx_data rx_data[R92C_MAX_EPIN][URTWN_RX_LIST_COUNT]; struct urtwn_tx_data tx_data[R92C_MAX_EPOUT][URTWN_TX_LIST_COUNT]; + struct urtwn_tx_data dummy_data[R92C_MAX_EPOUT][URTWN_TX_LIST_COUNT]; TAILQ_HEAD(, urtwn_tx_data) tx_free_list[R92C_MAX_EPOUT]; TAILQ_HEAD(, urtwn_rx_data) rx_free_list[R92C_MAX_EPIN]; + TAILQ_HEAD(, urtwn_tx_data) dummy_free_list[R92C_MAX_EPOUT]; struct r92c_rom rom; uint8_t r88e_rom[4096];