Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 Feb 2013 10:30:26 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r247261 - in user/adrian/net80211_tx/sys: dev/ath dev/iwn net80211
Message-ID:  <201302251030.r1PAUQT7029254@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Mon Feb 25 10:30:25 2013
New Revision: 247261
URL: http://svnweb.freebsd.org/changeset/base/247261

Log:
  Introduce a new net80211 TX IC lock, to serialise both the VAP and
  the IC frame processing.
  
  This is a temporary(ish) thing, mostly to get the TX handling "correct"
  for now.
  
  The overview:
  
  * The TX IC lock is grabbed before any vap or raw xmit calls occur that
    invoke the 802.11 setup path;
  * it explicitly occurs _before_ fast frame queuing and ampdu handling -
    + the ff queuing may or may not pair it with a second frame, and go
      through the encap path;
    + the ampdu path can actually send a management frame at this point,
      so this avoids a recursive call.
  * modify iwn and ath TX path to grab the net80211 TX lock if the driver
    TX start path is called deferred - eg, during reset, or TX completion.
    This ensures that the same locking is done and in the same order.
  
  It's inefficient but hopefully (!) correct enough to stop all of the
  subtle races..

Modified:
  user/adrian/net80211_tx/sys/dev/ath/if_ath.c
  user/adrian/net80211_tx/sys/dev/ath/if_ath_misc.h
  user/adrian/net80211_tx/sys/dev/ath/if_ath_tx.c
  user/adrian/net80211_tx/sys/dev/iwn/if_iwn.c
  user/adrian/net80211_tx/sys/net80211/ieee80211.c
  user/adrian/net80211_tx/sys/net80211/ieee80211_freebsd.h
  user/adrian/net80211_tx/sys/net80211/ieee80211_ht.c
  user/adrian/net80211_tx/sys/net80211/ieee80211_hwmp.c
  user/adrian/net80211_tx/sys/net80211/ieee80211_mesh.c
  user/adrian/net80211_tx/sys/net80211/ieee80211_output.c
  user/adrian/net80211_tx/sys/net80211/ieee80211_superg.c
  user/adrian/net80211_tx/sys/net80211/ieee80211_var.h

Modified: user/adrian/net80211_tx/sys/dev/ath/if_ath.c
==============================================================================
--- user/adrian/net80211_tx/sys/dev/ath/if_ath.c	Mon Feb 25 10:07:54 2013	(r247260)
+++ user/adrian/net80211_tx/sys/dev/ath/if_ath.c	Mon Feb 25 10:30:25 2013	(r247261)
@@ -2525,9 +2525,14 @@ static void
 ath_start_queue(struct ifnet *ifp)
 {
 	struct ath_softc *sc = ifp->if_softc;
+	struct ieee80211com *ic = ifp->if_l2com;
+
+	IEEE80211_TX_LOCK_ASSERT(ic);
 
 	ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_queue: start");
-	ath_tx_kick(sc);
+	ATH_TX_LOCK(sc);
+	ath_start(ifp);
+	ATH_TX_UNLOCK(sc);
 	ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_queue: finished");
 }
 
@@ -2535,6 +2540,7 @@ void
 ath_start_task(void *arg, int npending)
 {
 	struct ath_softc *sc = (struct ath_softc *) arg;
+	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
 	struct ifnet *ifp = sc->sc_ifp;
 
 	ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_task: start");
@@ -2555,9 +2561,11 @@ ath_start_task(void *arg, int npending)
 	sc->sc_txstart_cnt++;
 	ATH_PCU_UNLOCK(sc);
 
+	IEEE80211_TX_LOCK(ic);
 	ATH_TX_LOCK(sc);
 	ath_start(sc->sc_ifp);
 	ATH_TX_UNLOCK(sc);
+	IEEE80211_TX_UNLOCK(ic);
 
 	ATH_PCU_LOCK(sc);
 	sc->sc_txstart_cnt--;
@@ -2569,6 +2577,7 @@ void
 ath_start(struct ifnet *ifp)
 {
 	struct ath_softc *sc = ifp->if_softc;
+	struct ieee80211com *ic = ifp->if_l2com;
 	struct ieee80211_node *ni;
 	struct ath_buf *bf;
 	struct mbuf *m, *next;
@@ -2578,6 +2587,7 @@ ath_start(struct ifnet *ifp)
 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid)
 		return;
 
+	IEEE80211_TX_LOCK_ASSERT(ic);
 	ATH_TX_LOCK_ASSERT(sc);
 
 	ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start: called");

Modified: user/adrian/net80211_tx/sys/dev/ath/if_ath_misc.h
==============================================================================
--- user/adrian/net80211_tx/sys/dev/ath/if_ath_misc.h	Mon Feb 25 10:07:54 2013	(r247260)
+++ user/adrian/net80211_tx/sys/dev/ath/if_ath_misc.h	Mon Feb 25 10:30:25 2013	(r247261)
@@ -126,10 +126,16 @@ extern	void ath_start_task(void *arg, in
 static inline void
 ath_tx_kick(struct ath_softc *sc)
 {
+	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
 
+	IEEE80211_TX_UNLOCK_ASSERT(ic);
+	ATH_TX_UNLOCK_ASSERT(sc);
+
+	IEEE80211_TX_LOCK(ic);
 	ATH_TX_LOCK(sc);
 	ath_start(sc->sc_ifp);
 	ATH_TX_UNLOCK(sc);
+	IEEE80211_TX_UNLOCK(ic);
 }
 
 /*

Modified: user/adrian/net80211_tx/sys/dev/ath/if_ath_tx.c
==============================================================================
--- user/adrian/net80211_tx/sys/dev/ath/if_ath_tx.c	Mon Feb 25 10:07:54 2013	(r247260)
+++ user/adrian/net80211_tx/sys/dev/ath/if_ath_tx.c	Mon Feb 25 10:30:25 2013	(r247261)
@@ -1772,6 +1772,7 @@ ath_tx_start(struct ath_softc *sc, struc
     struct ath_buf *bf, struct mbuf *m0)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
+	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
 	struct ath_vap *avp = ATH_VAP(vap);
 	int r = 0;
 	u_int pri;
@@ -1784,6 +1785,7 @@ ath_tx_start(struct ath_softc *sc, struc
 	uint8_t type, subtype;
 
 	ATH_TX_LOCK_ASSERT(sc);
+	IEEE80211_TX_LOCK_ASSERT(ic);
 
 	/*
 	 * Determine the target hardware queue.
@@ -1971,6 +1973,7 @@ ath_tx_raw_start(struct ath_softc *sc, s
 	int do_override;
 
 	ATH_TX_LOCK_ASSERT(sc);
+	IEEE80211_TX_LOCK_ASSERT(ic);
 
 	wh = mtod(m0, struct ieee80211_frame *);
 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
@@ -4996,8 +4999,15 @@ void
 ath_txq_sched(struct ath_softc *sc, struct ath_txq *txq)
 {
 	struct ath_tid *tid, *next, *last;
+	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
 
 	ATH_TX_LOCK_ASSERT(sc);
+	/*
+	 * This shouldn't be directly called from the TX queue
+	 * code path; it should be called from the TX completion
+	 * or TX kick task.
+	 */
+	IEEE80211_TX_UNLOCK_ASSERT(ic);
 
 	/*
 	 * Don't schedule if the hardware queue is busy.

Modified: user/adrian/net80211_tx/sys/dev/iwn/if_iwn.c
==============================================================================
--- user/adrian/net80211_tx/sys/dev/iwn/if_iwn.c	Mon Feb 25 10:07:54 2013	(r247260)
+++ user/adrian/net80211_tx/sys/dev/iwn/if_iwn.c	Mon Feb 25 10:30:25 2013	(r247261)
@@ -2716,6 +2716,7 @@ iwn_tx_done(struct iwn_softc *sc, struct
 	struct mbuf *m;
 	struct ieee80211_node *ni;
 	struct ieee80211vap *vap;
+	struct ieee80211com *ic = ifp->if_l2com;
 
 	KASSERT(data->ni != NULL, ("no node"));
 
@@ -2770,7 +2771,16 @@ iwn_tx_done(struct iwn_softc *sc, struct
 		if (sc->qfullmsk == 0 &&
 		    (ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
 			ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+			/*
+			 * XXX turn this into a deferred taskqueue at some point.
+			 */
+			IWN_UNLOCK(sc);
+
+			IEEE80211_TX_LOCK(ic);
+			IWN_LOCK(sc);
 			iwn_start_locked(ifp);
+			IWN_UNLOCK(sc);
+			IEEE80211_TX_UNLOCK(ic);
 		}
 	}
 }
@@ -2807,6 +2817,7 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, 
 {
 	struct iwn_ops *ops = &sc->ops;
 	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	struct iwn_tx_ring *ring = &sc->txq[qid];
 	struct iwn_tx_data *data;
 	struct mbuf *m;
@@ -2903,6 +2914,18 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, 
 		if (sc->qfullmsk == 0 &&
 		    (ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
 			ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+			/*
+			 * XXX turn this into a deferred taskqueue at some point.
+			 */
+			IWN_UNLOCK(sc);
+
+			IEEE80211_TX_LOCK(ic);
+			IWN_LOCK(sc);
+			iwn_start_locked(ifp);
+			IWN_UNLOCK(sc);
+			IEEE80211_TX_UNLOCK(ic);
+
 			iwn_start_locked(ifp);
 		}
 	}
@@ -3850,6 +3873,9 @@ static void
 iwn_start(struct ifnet *ifp)
 {
 	struct iwn_softc *sc = ifp->if_softc;
+	struct ieee80211com *ic = ifp->if_l2com;
+
+	IEEE80211_TX_LOCK_ASSERT(ic);
 
 	IWN_LOCK(sc);
 	iwn_start_locked(ifp);
@@ -3860,10 +3886,12 @@ static void
 iwn_start_locked(struct ifnet *ifp)
 {
 	struct iwn_softc *sc = ifp->if_softc;
+	struct ieee80211com *ic = ifp->if_l2com;
 	struct ieee80211_node *ni;
 	struct mbuf *m;
 
 	IWN_LOCK_ASSERT(sc);
+	IEEE80211_TX_LOCK_ASSERT(ic);
 
 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
 	    (ifp->if_drv_flags & IFF_DRV_OACTIVE))

Modified: user/adrian/net80211_tx/sys/net80211/ieee80211.c
==============================================================================
--- user/adrian/net80211_tx/sys/net80211/ieee80211.c	Mon Feb 25 10:07:54 2013	(r247260)
+++ user/adrian/net80211_tx/sys/net80211/ieee80211.c	Mon Feb 25 10:30:25 2013	(r247261)
@@ -278,6 +278,7 @@ ieee80211_ifattach(struct ieee80211com *
 	KASSERT(ifp->if_type == IFT_IEEE80211, ("if_type %d", ifp->if_type));
 
 	IEEE80211_LOCK_INIT(ic, ifp->if_xname);
+	IEEE80211_TX_LOCK_INIT(ic, ifp->if_xname);
 	TAILQ_INIT(&ic->ic_vaps);
 
 	/* Create a taskqueue for all state changes */
@@ -385,6 +386,7 @@ ieee80211_ifdetach(struct ieee80211com *
 	ifmedia_removeall(&ic->ic_media);
 
 	taskqueue_free(ic->ic_tq);
+	IEEE80211_TX_LOCK_DESTROY(ic);
 	IEEE80211_LOCK_DESTROY(ic);
 }
 

Modified: user/adrian/net80211_tx/sys/net80211/ieee80211_freebsd.h
==============================================================================
--- user/adrian/net80211_tx/sys/net80211/ieee80211_freebsd.h	Mon Feb 25 10:07:54 2013	(r247260)
+++ user/adrian/net80211_tx/sys/net80211/ieee80211_freebsd.h	Mon Feb 25 10:30:25 2013	(r247261)
@@ -57,6 +57,30 @@ typedef struct {
 	mtx_assert(IEEE80211_LOCK_OBJ(_ic), MA_NOTOWNED)
 
 /*
+ * Transmit lock.
+ *
+ * This is a (mostly) temporary lock designed to serialise all of the
+ * transmission operations throughout the stack.
+ */
+typedef struct {
+	char		name[16];		/* e.g. "ath0_com_lock" */
+	struct mtx	mtx;
+} ieee80211_tx_lock_t;
+#define	IEEE80211_TX_LOCK_INIT(_ic, _name) do {				\
+	ieee80211_tx_lock_t *cl = &(_ic)->ic_txlock;			\
+	snprintf(cl->name, sizeof(cl->name), "%s_tx_lock", _name);	\
+	mtx_init(&cl->mtx, cl->name, NULL, MTX_DEF);	\
+} while (0)
+#define	IEEE80211_TX_LOCK_OBJ(_ic)	(&(_ic)->ic_txlock.mtx)
+#define	IEEE80211_TX_LOCK_DESTROY(_ic) mtx_destroy(IEEE80211_TX_LOCK_OBJ(_ic))
+#define	IEEE80211_TX_LOCK(_ic)	   mtx_lock(IEEE80211_TX_LOCK_OBJ(_ic))
+#define	IEEE80211_TX_UNLOCK(_ic)	   mtx_unlock(IEEE80211_TX_LOCK_OBJ(_ic))
+#define	IEEE80211_TX_LOCK_ASSERT(_ic) \
+	mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_OWNED)
+#define	IEEE80211_TX_UNLOCK_ASSERT(_ic) \
+	mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_NOTOWNED)
+
+/*
  * Node locking definitions.
  */
 typedef struct {

Modified: user/adrian/net80211_tx/sys/net80211/ieee80211_ht.c
==============================================================================
--- user/adrian/net80211_tx/sys/net80211/ieee80211_ht.c	Mon Feb 25 10:07:54 2013	(r247260)
+++ user/adrian/net80211_tx/sys/net80211/ieee80211_ht.c	Mon Feb 25 10:30:25 2013	(r247261)
@@ -2392,7 +2392,9 @@ ieee80211_send_bar(struct ieee80211_node
 	 * ic_raw_xmit will free the node reference
 	 * regardless of queue/TX success or failure.
 	 */
+	IEEE80211_TX_LOCK(ic);
 	ret = ic->ic_raw_xmit(ni, m, NULL);
+	IEEE80211_TX_UNLOCK(ic);
 	if (ret != 0) {
 		IEEE80211_NOTE(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_11N,
 		    ni, "send BAR: failed: (ret = %d)\n",

Modified: user/adrian/net80211_tx/sys/net80211/ieee80211_hwmp.c
==============================================================================
--- user/adrian/net80211_tx/sys/net80211/ieee80211_hwmp.c	Mon Feb 25 10:07:54 2013	(r247260)
+++ user/adrian/net80211_tx/sys/net80211/ieee80211_hwmp.c	Mon Feb 25 10:30:25 2013	(r247261)
@@ -592,6 +592,7 @@ hwmp_send_action(struct ieee80211vap *va
 	struct ieee80211_bpf_params params;
 	struct mbuf *m;
 	uint8_t *frm;
+	int ret;
 
 	if (IEEE80211_IS_MULTICAST(da)) {
 		ni = ieee80211_ref_node(vap->iv_bss);
@@ -654,6 +655,9 @@ hwmp_send_action(struct ieee80211vap *va
 		vap->iv_stats.is_tx_nobuf++;
 		return ENOMEM;
 	}
+
+	IEEE80211_TX_LOCK(ic);
+
 	ieee80211_send_setup(ni, m,
 	    IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION,
 	    IEEE80211_NONQOS_TID, vap->iv_myaddr, da, vap->iv_myaddr);
@@ -669,7 +673,9 @@ hwmp_send_action(struct ieee80211vap *va
 	else
 		params.ibp_try0 = ni->ni_txparms->maxretry;
 	params.ibp_power = ni->ni_txpower;
-	return ic->ic_raw_xmit(ni, m, &params);
+	ret = ic->ic_raw_xmit(ni, m, &params);
+	IEEE80211_TX_UNLOCK(ic);
+	return (ret);
 }
 
 #define ADDSHORT(frm, v) do {		\

Modified: user/adrian/net80211_tx/sys/net80211/ieee80211_mesh.c
==============================================================================
--- user/adrian/net80211_tx/sys/net80211/ieee80211_mesh.c	Mon Feb 25 10:07:54 2013	(r247260)
+++ user/adrian/net80211_tx/sys/net80211/ieee80211_mesh.c	Mon Feb 25 10:30:25 2013	(r247261)
@@ -2743,6 +2743,7 @@ mesh_send_action(struct ieee80211_node *
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ieee80211_bpf_params params;
 	struct ieee80211_frame *wh;
+	int ret;
 
 	KASSERT(ni != NULL, ("null node"));
 
@@ -2761,6 +2762,7 @@ mesh_send_action(struct ieee80211_node *
 		return ENOMEM;
 	}
 
+	IEEE80211_TX_LOCK(ic);
 	wh = mtod(m, struct ieee80211_frame *);
 	ieee80211_send_setup(ni, m,
 	     IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION,
@@ -2778,7 +2780,9 @@ mesh_send_action(struct ieee80211_node *
 
 	IEEE80211_NODE_STAT(ni, tx_mgmt);
 
-	return ic->ic_raw_xmit(ni, m, &params);
+	ret = ic->ic_raw_xmit(ni, m, &params);
+	IEEE80211_TX_UNLOCK(ic);
+	return (ret);
 }
 
 #define	ADDSHORT(frm, v) do {			\

Modified: user/adrian/net80211_tx/sys/net80211/ieee80211_output.c
==============================================================================
--- user/adrian/net80211_tx/sys/net80211/ieee80211_output.c	Mon Feb 25 10:07:54 2013	(r247260)
+++ user/adrian/net80211_tx/sys/net80211/ieee80211_output.c	Mon Feb 25 10:30:25 2013	(r247261)
@@ -282,6 +282,7 @@ ieee80211_start_pkt(struct ieee80211vap 
 
 	BPF_MTAP(ifp, m);		/* 802.3 tx */
 
+
 	/*
 	 * Check if A-MPDU tx aggregation is setup or if we
 	 * should try to enable it.  The sta must be associated
@@ -317,6 +318,7 @@ ieee80211_start_pkt(struct ieee80211vap 
 			/* XXX hold frame for reply? */
 		}
 	}
+
 #ifdef IEEE80211_SUPPORT_SUPERG
 	else if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF)) {
 		m = ieee80211_ff_check(ni, m);
@@ -327,6 +329,14 @@ ieee80211_start_pkt(struct ieee80211vap 
 		}
 	}
 #endif /* IEEE80211_SUPPORT_SUPERG */
+
+	/*
+	 * Grab the TX lock - serialise the TX process from this
+	 * point (where TX state is being checked/modified)
+	 * through to driver queue.
+	 */
+	IEEE80211_TX_LOCK(ic);
+
 	if (__predict_true((vap->iv_caps & IEEE80211_C_8023ENCAP) == 0)) {
 		/*
 		 * Encapsulate the packet in prep for transmission.
@@ -334,12 +344,19 @@ ieee80211_start_pkt(struct ieee80211vap 
 		m = ieee80211_encap(vap, ni, m);
 		if (m == NULL) {
 			/* NB: stat+msg handled in ieee80211_encap */
+			IEEE80211_TX_UNLOCK(ic);
 			ieee80211_free_node(ni);
 			/* XXX better status? */
 			return (ENOBUFS);
 		}
 	}
 	error = parent->if_transmit(parent, m);
+
+	/*
+	 * Unlock at this point - no need to hold it across
+	 * ieee80211_free_node() (ie, the comlock)
+	 */
+	IEEE80211_TX_UNLOCK(ic);
 	if (error != 0) {
 		/* NB: IFQ_HANDOFF reclaims mbuf */
 		ieee80211_free_node(ni);
@@ -425,7 +442,9 @@ ieee80211_output(struct ifnet *ifp, stru
 	struct ieee80211_node *ni = NULL;
 	struct ieee80211vap *vap;
 	struct ieee80211_frame *wh;
+	struct ieee80211com *ic = NULL;
 	int error;
+	int ret;
 
 	IFQ_LOCK(&ifp->if_snd);
 	if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
@@ -442,6 +461,7 @@ ieee80211_output(struct ifnet *ifp, stru
 	}
 	IFQ_UNLOCK(&ifp->if_snd);
 	vap = ifp->if_softc;
+	ic = vap->iv_ic;
 	/*
 	 * Hand to the 802.3 code if not tagged as
 	 * a raw 802.11 frame.
@@ -522,15 +542,19 @@ ieee80211_output(struct ifnet *ifp, stru
 	/* NB: ieee80211_encap does not include 802.11 header */
 	IEEE80211_NODE_STAT_ADD(ni, tx_bytes, m->m_pkthdr.len);
 
+	IEEE80211_TX_LOCK(ic);
+
 	/*
 	 * NB: DLT_IEEE802_11_RADIO identifies the parameters are
 	 * present by setting the sa_len field of the sockaddr (yes,
 	 * this is a hack).
 	 * NB: we assume sa_data is suitably aligned to cast.
 	 */
-	return vap->iv_ic->ic_raw_xmit(ni, m,
+	ret = vap->iv_ic->ic_raw_xmit(ni, m,
 	    (const struct ieee80211_bpf_params *)(dst->sa_len ?
 		dst->sa_data : NULL));
+	IEEE80211_TX_UNLOCK(ic);
+	return (ret);
 bad:
 	if (m != NULL)
 		m_freem(m);
@@ -559,8 +583,11 @@ ieee80211_send_setup(
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211_tx_ampdu *tap;
 	struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
+	struct ieee80211com *ic = ni->ni_ic;
 	ieee80211_seq seqno;
 
+	IEEE80211_TX_LOCK_ASSERT(ic);
+
 	wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | type;
 	if ((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) {
 		switch (vap->iv_opmode) {
@@ -654,6 +681,7 @@ ieee80211_mgmt_output(struct ieee80211_n
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ieee80211_frame *wh;
+	int ret;
 
 	KASSERT(ni != NULL, ("null node"));
 
@@ -675,6 +703,8 @@ ieee80211_mgmt_output(struct ieee80211_n
 		return ENOMEM;
 	}
 
+	IEEE80211_TX_LOCK(ic);
+
 	wh = mtod(m, struct ieee80211_frame *);
 	ieee80211_send_setup(ni, m,
 	     IEEE80211_FC0_TYPE_MGT | type, IEEE80211_NONQOS_TID,
@@ -703,7 +733,9 @@ ieee80211_mgmt_output(struct ieee80211_n
 #endif
 	IEEE80211_NODE_STAT(ni, tx_mgmt);
 
-	return ic->ic_raw_xmit(ni, m, params);
+	ret = ic->ic_raw_xmit(ni, m, params);
+	IEEE80211_TX_UNLOCK(ic);
+	return (ret);
 }
 
 /*
@@ -727,6 +759,7 @@ ieee80211_send_nulldata(struct ieee80211
 	struct ieee80211_frame *wh;
 	int hdrlen;
 	uint8_t *frm;
+	int ret;
 
 	if (vap->iv_state == IEEE80211_S_CAC) {
 		IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT | IEEE80211_MSG_DOTH,
@@ -762,6 +795,8 @@ ieee80211_send_nulldata(struct ieee80211
 		return ENOMEM;
 	}
 
+	IEEE80211_TX_LOCK(ic);
+
 	wh = mtod(m, struct ieee80211_frame *);		/* NB: a little lie */
 	if (ni->ni_flags & IEEE80211_NODE_QOS) {
 		const int tid = WME_AC_TO_TID(WME_AC_BE);
@@ -804,7 +839,9 @@ ieee80211_send_nulldata(struct ieee80211
 	    ieee80211_chan2ieee(ic, ic->ic_curchan),
 	    wh->i_fc[1] & IEEE80211_FC1_PWR_MGT ? "ena" : "dis");
 
-	return ic->ic_raw_xmit(ni, m, NULL);
+	ret = ic->ic_raw_xmit(ni, m, NULL);
+	IEEE80211_TX_UNLOCK(ic);
+	return (ret);
 }
 
 /* 
@@ -1067,6 +1104,8 @@ ieee80211_encap(struct ieee80211vap *vap
 	ieee80211_seq seqno;
 	int meshhdrsize, meshae;
 	uint8_t *qos;
+	
+	IEEE80211_TX_LOCK_ASSERT(ic);
 
 	/*
 	 * Copy existing Ethernet header to a safe place.  The
@@ -1839,6 +1878,7 @@ ieee80211_send_probereq(struct ieee80211
 	const struct ieee80211_rateset *rs;
 	struct mbuf *m;
 	uint8_t *frm;
+	int ret;
 
 	if (vap->iv_state == IEEE80211_S_CAC) {
 		IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni,
@@ -1911,6 +1951,7 @@ ieee80211_send_probereq(struct ieee80211
 		return ENOMEM;
 	}
 
+	IEEE80211_TX_LOCK(ic);
 	wh = mtod(m, struct ieee80211_frame *);
 	ieee80211_send_setup(ni, m,
 	     IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ,
@@ -1938,7 +1979,9 @@ ieee80211_send_probereq(struct ieee80211
 	} else
 		params.ibp_try0 = tp->maxretry;
 	params.ibp_power = ni->ni_txpower;
-	return ic->ic_raw_xmit(ni, m, &params);
+	ret = ic->ic_raw_xmit(ni, m, &params);
+	IEEE80211_TX_UNLOCK(ic);
+	return (ret);
 }
 
 /*
@@ -2507,6 +2550,7 @@ ieee80211_send_proberesp(struct ieee8021
 	struct ieee80211com *ic = vap->iv_ic;
 	struct ieee80211_frame *wh;
 	struct mbuf *m;
+	int ret;
 
 	if (vap->iv_state == IEEE80211_S_CAC) {
 		IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, bss,
@@ -2535,6 +2579,7 @@ ieee80211_send_proberesp(struct ieee8021
 	M_PREPEND(m, sizeof(struct ieee80211_frame), M_NOWAIT);
 	KASSERT(m != NULL, ("no room for header"));
 
+	IEEE80211_TX_LOCK(ic);
 	wh = mtod(m, struct ieee80211_frame *);
 	ieee80211_send_setup(bss, m,
 	     IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP,
@@ -2550,7 +2595,9 @@ ieee80211_send_proberesp(struct ieee8021
 	    legacy ? " <legacy>" : "");
 	IEEE80211_NODE_STAT(bss, tx_mgmt);
 
-	return ic->ic_raw_xmit(bss, m, NULL);
+	ret = ic->ic_raw_xmit(bss, m, NULL);
+	IEEE80211_TX_UNLOCK(ic);
+	return (ret);
 }
 
 /*

Modified: user/adrian/net80211_tx/sys/net80211/ieee80211_superg.c
==============================================================================
--- user/adrian/net80211_tx/sys/net80211/ieee80211_superg.c	Mon Feb 25 10:07:54 2013	(r247260)
+++ user/adrian/net80211_tx/sys/net80211/ieee80211_superg.c	Mon Feb 25 10:30:25 2013	(r247261)
@@ -503,6 +503,8 @@ ff_transmit(struct ieee80211_node *ni, s
 	struct ieee80211vap *vap = ni->ni_vap;
 	int error;
 
+	IEEE80211_TX_LOCK_ASSERT(vap->iv_ic);
+
 	/* encap and xmit */
 	m = ieee80211_encap(vap, ni, m);
 	if (m != NULL) {
@@ -532,6 +534,8 @@ ff_flush(struct mbuf *head, struct mbuf 
 	struct ieee80211_node *ni;
 	struct ieee80211vap *vap;
 
+	IEEE80211_TX_LOCK_ASSERT(vap->iv_ic);
+
 	for (m = head; m != last; m = next) {
 		next = m->m_nextpkt;
 		m->m_nextpkt = NULL;
@@ -590,7 +594,9 @@ ieee80211_ff_age(struct ieee80211com *ic
 		M_AGE_SUB(m, quanta);
 	IEEE80211_UNLOCK(ic);
 
+	IEEE80211_TX_LOCK(ic);
 	ff_flush(head, m);
+	IEEE80211_TX_UNLOCK(ic);
 }
 
 static void
@@ -679,6 +685,8 @@ ieee80211_ff_check(struct ieee80211_node
 	struct mbuf *mstaged;
 	uint32_t txtime, limit;
 
+	IEEE80211_TX_UNLOCK_ASSERT(ic);
+
 	/*
 	 * Check if the supplied frame can be aggregated.
 	 *
@@ -734,10 +742,12 @@ ieee80211_ff_check(struct ieee80211_node
 		IEEE80211_UNLOCK(ic);
 
 		if (mstaged != NULL) {
+			IEEE80211_TX_LOCK(ic);
 			IEEE80211_NOTE(vap, IEEE80211_MSG_SUPERG, ni,
 			    "%s: flush staged frame", __func__);
 			/* encap and xmit */
 			ff_transmit(ni, mstaged);
+			IEEE80211_TX_UNLOCK(ic);
 		}
 		return m;		/* NB: original frame */
 	}

Modified: user/adrian/net80211_tx/sys/net80211/ieee80211_var.h
==============================================================================
--- user/adrian/net80211_tx/sys/net80211/ieee80211_var.h	Mon Feb 25 10:07:54 2013	(r247260)
+++ user/adrian/net80211_tx/sys/net80211/ieee80211_var.h	Mon Feb 25 10:30:25 2013	(r247261)
@@ -118,6 +118,7 @@ struct ieee80211_frame;
 struct ieee80211com {
 	struct ifnet		*ic_ifp;	/* associated device */
 	ieee80211_com_lock_t	ic_comlock;	/* state update lock */
+	ieee80211_tx_lock_t	ic_txlock;	/* ic/vap TX lock */
 	TAILQ_HEAD(, ieee80211vap) ic_vaps;	/* list of vap instances */
 	int			ic_headroom;	/* driver tx headroom needs */
 	enum ieee80211_phytype	ic_phytype;	/* XXX wrong for multi-mode */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201302251030.r1PAUQT7029254>