mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-19 10:53:58 +00:00
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.
This commit is contained in:
parent
829e0b0b84
commit
77435f1835
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=288052
@ -190,6 +190,7 @@ static uint8_t rsu_efuse_read_1(struct rsu_softc *, uint16_t);
|
||||
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 ieee80211_node *,
|
||||
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 __unused)
|
||||
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, enum ieee80211_state nstate, int arg)
|
||||
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 @@ rsu_bulk_tx_callback_sub(struct usb_xfer *xfer, usb_error_t error,
|
||||
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, struct mbuf *m)
|
||||
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;
|
||||
@ -2062,6 +2094,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)
|
||||
{
|
||||
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user