svn commit: r288052 - head/sys/dev/usb/wlan
Adrian Chadd
adrian at FreeBSD.org
Mon Sep 21 02:30:24 UTC 2015
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;
More information about the svn-src-head
mailing list