Date: Mon, 21 Sep 2015 02:30:23 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r288052 - head/sys/dev/usb/wlan Message-ID: <201509210230.t8L2UNcs039369@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Mon Sep 21 02:30:22 2015 New Revision: 288052 URL: https://svnweb.freebsd.org/changeset/base/288052 Log: Convert if_rsu to use a deferred transmit task rather than using rsu_start() to do it directly. Ensure that we re-queue starting transmit upon TX completion. This solves two issues: * It stops tx stalls - before this, if the transmit path filled the mbuf queue then it'd never start another transmit. * It enforces ordering - this is very required for 802.11n which requires frames to be transmitted in the order they're queued. Since everything remotely involved in USB has an unlock/thing/relock pattern with that mutex, the only way to guarantee TX ordering is to 100% defer it into a separate thread. This now survives an iperf test and gets a reliable 30mbit/sec. Modified: head/sys/dev/usb/wlan/if_rsu.c head/sys/dev/usb/wlan/if_rsureg.h Modified: head/sys/dev/usb/wlan/if_rsu.c ============================================================================== --- head/sys/dev/usb/wlan/if_rsu.c Mon Sep 21 02:12:01 2015 (r288051) +++ head/sys/dev/usb/wlan/if_rsu.c Mon Sep 21 02:30:22 2015 (r288052) @@ -190,6 +190,7 @@ static uint8_t rsu_efuse_read_1(struct r static int rsu_read_rom(struct rsu_softc *); static int rsu_fw_cmd(struct rsu_softc *, uint8_t, void *, int); static void rsu_calib_task(void *, int); +static void rsu_tx_task(void *, int); static int rsu_newstate(struct ieee80211vap *, enum ieee80211_state, int); #ifdef notyet static void rsu_set_key(struct rsu_softc *, const struct ieee80211_key *); @@ -217,6 +218,7 @@ static int rsu_tx_start(struct rsu_softc struct mbuf *, struct rsu_data *); static int rsu_transmit(struct ieee80211com *, struct mbuf *); static void rsu_start(struct rsu_softc *); +static void _rsu_start(struct rsu_softc *); static void rsu_parent(struct ieee80211com *); static void rsu_stop(struct rsu_softc *); static void rsu_ms_delay(struct rsu_softc *, int); @@ -379,6 +381,7 @@ rsu_attach(device_t self) MTX_DEF); TIMEOUT_TASK_INIT(taskqueue_thread, &sc->calib_task, 0, rsu_calib_task, sc); + TASK_INIT(&sc->tx_task, 0, rsu_tx_task, sc); mbufq_init(&sc->sc_snd, ifqmaxlen); /* Allocate Tx/Rx buffers. */ @@ -513,6 +516,7 @@ rsu_detach(device_t self) ieee80211_ifdetach(ic); taskqueue_drain_timeout(taskqueue_thread, &sc->calib_task); + taskqueue_drain(taskqueue_thread, &sc->tx_task); /* Free Tx/Rx buffers. */ rsu_free_tx_list(sc); @@ -1026,6 +1030,16 @@ rsu_calib_task(void *arg, int pending __ RSU_UNLOCK(sc); } +static void +rsu_tx_task(void *arg, int pending __unused) +{ + struct rsu_softc *sc = arg; + + RSU_LOCK(sc); + _rsu_start(sc); + RSU_UNLOCK(sc); +} + static int rsu_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { @@ -1050,6 +1064,7 @@ rsu_newstate(struct ieee80211vap *vap, e sc->sc_calibrating = 0; RSU_UNLOCK(sc); taskqueue_drain_timeout(taskqueue_thread, &sc->calib_task); + taskqueue_drain(taskqueue_thread, &sc->tx_task); /* Disassociate from our current BSS. */ RSU_LOCK(sc); rsu_disconnect(sc); @@ -1838,19 +1853,34 @@ tr_setup: static void rsu_bulk_tx_callback_be_bk(struct usb_xfer *xfer, usb_error_t error) { + struct rsu_softc *sc = usbd_xfer_softc(xfer); + rsu_bulk_tx_callback_sub(xfer, error, RSU_BULK_TX_BE_BK); + + /* This kicks the TX taskqueue */ + rsu_start(sc); } static void rsu_bulk_tx_callback_vi_vo(struct usb_xfer *xfer, usb_error_t error) { + struct rsu_softc *sc = usbd_xfer_softc(xfer); + rsu_bulk_tx_callback_sub(xfer, error, RSU_BULK_TX_VI_VO); + + /* This kicks the TX taskqueue */ + rsu_start(sc); } static void rsu_bulk_tx_callback_h2c(struct usb_xfer *xfer, usb_error_t error) { + struct rsu_softc *sc = usbd_xfer_softc(xfer); + rsu_bulk_tx_callback_sub(xfer, error, RSU_BULK_TX_H2C); + + /* This kicks the TX taskqueue */ + rsu_start(sc); } static int @@ -2008,9 +2038,11 @@ rsu_transmit(struct ieee80211com *ic, st RSU_UNLOCK(sc); return (error); } - rsu_start(sc); RSU_UNLOCK(sc); + /* This kicks the TX taskqueue */ + rsu_start(sc); + return (0); } @@ -2030,7 +2062,7 @@ rsu_drain_mbufq(struct rsu_softc *sc) } static void -rsu_start(struct rsu_softc *sc) +_rsu_start(struct rsu_softc *sc) { struct ieee80211_node *ni; struct rsu_data *bf; @@ -2063,6 +2095,13 @@ rsu_start(struct rsu_softc *sc) } static void +rsu_start(struct rsu_softc *sc) +{ + + taskqueue_enqueue(taskqueue_thread, &sc->tx_task); +} + +static void rsu_parent(struct ieee80211com *ic) { struct rsu_softc *sc = ic->ic_softc; @@ -2684,6 +2723,7 @@ rsu_stop(struct rsu_softc *sc) sc->sc_running = 0; sc->sc_calibrating = 0; taskqueue_cancel_timeout(taskqueue_thread, &sc->calib_task, NULL); + taskqueue_cancel(taskqueue_thread, &sc->tx_task, NULL); /* Power off adapter. */ rsu_power_off(sc); Modified: head/sys/dev/usb/wlan/if_rsureg.h ============================================================================== --- head/sys/dev/usb/wlan/if_rsureg.h Mon Sep 21 02:12:01 2015 (r288051) +++ head/sys/dev/usb/wlan/if_rsureg.h Mon Sep 21 02:30:22 2015 (r288052) @@ -740,6 +740,7 @@ struct rsu_softc { enum ieee80211_state, int); struct usbd_interface *sc_iface; struct timeout_task calib_task; + struct task tx_task; const uint8_t *qid2idx; struct mtx sc_mtx; int sc_ht;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201509210230.t8L2UNcs039369>