Skip site navigation (1)Skip section navigation (2)
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>