1
0
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:
Adrian Chadd 2015-09-21 02:30:22 +00:00
parent 829e0b0b84
commit 77435f1835
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=288052
2 changed files with 43 additions and 2 deletions

View File

@ -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);

View File

@ -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;