diff options
author | adrian <adrian@FreeBSD.org> | 2013-01-26 00:14:34 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2013-01-26 00:14:34 +0000 |
commit | 70d3c0881d5d5c65ccd952e336c71ac8bd75f3a6 (patch) | |
tree | d45d21076ed38c6e3c5b40be02f893a26e83bfbf | |
parent | 1758ec476211c85d75eaa80aa708cb454b914398 (diff) | |
download | FreeBSD-src-70d3c0881d5d5c65ccd952e336c71ac8bd75f3a6.zip FreeBSD-src-70d3c0881d5d5c65ccd952e336c71ac8bd75f3a6.tar.gz |
Migrate the TX sending code out from under the ath0 taskq and into
the separate ath0 TX taskq.
Whilst here, make sure that the TX software scheduler is also
running out of the TX task, rather than the ath0 taskqueue.
Make sure that the tx taskqueue is blocked/unblocked as necessary.
This allows for a little more parallelism on multi-core machines,
as well as (eventually) supporting a higher task priority for TX
tasks, allowing said TX task to preempt an already running RX or
TX completion task.
Tested:
* AR5416, AR9280 hostap and STA modes
-rw-r--r-- | sys/dev/ath/if_ath.c | 22 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_misc.h | 2 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_tx.c | 2 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_tx_edma.c | 2 |
4 files changed, 22 insertions, 6 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 9fc182f..41019fb 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -436,6 +436,16 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq", ifp->if_xname); + /* + * This taskqueue doesn't get any higher priority + * than the ath(4) taskqueue (PI_NET) so TX won't + * pre-empt RX and other task priorities. + * + * This may not be optimal - the previous behaviour + * was to direct-dispatch frames via the sending + * task context, rather than (always) software + * queuing. + */ sc->sc_tx_tq = taskqueue_create("ath_tx_taskq", M_NOWAIT, taskqueue_thread_enqueue, &sc->sc_tx_tq); taskqueue_start_threads(&sc->sc_tx_tq, 1, PI_NET, @@ -2135,6 +2145,7 @@ ath_txrx_start(struct ath_softc *sc) { taskqueue_unblock(sc->sc_tq); + taskqueue_unblock(sc->sc_tx_tq); } /* @@ -2235,6 +2246,7 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) /* Try to (stop any further TX/RX from occuring */ taskqueue_block(sc->sc_tq); + taskqueue_block(sc->sc_tx_tq); ATH_PCU_LOCK(sc); ath_hal_intrset(ah, 0); /* disable interrupts */ @@ -3033,6 +3045,7 @@ ath_key_update_begin(struct ieee80211vap *vap) DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__); taskqueue_block(sc->sc_tq); + taskqueue_block(sc->sc_tx_tq); IF_LOCK(&ifp->if_snd); /* NB: doesn't block mgmt frames */ } @@ -3045,6 +3058,7 @@ ath_key_update_end(struct ieee80211vap *vap) DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__); IF_UNLOCK(&ifp->if_snd); taskqueue_unblock(sc->sc_tq); + taskqueue_unblock(sc->sc_tx_tq); } static void @@ -4218,9 +4232,7 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched) /* Kick the TXQ scheduler */ if (dosched) { - ATH_TX_LOCK(sc); - ath_txq_sched(sc, txq); - ATH_TX_UNLOCK(sc); + taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask); } ATH_KTR(sc, ATH_KTR_TXCOMP, 1, @@ -4718,6 +4730,7 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) /* (Try to) stop TX/RX from occuring */ taskqueue_block(sc->sc_tq); + taskqueue_block(sc->sc_tx_tq); ATH_PCU_LOCK(sc); ath_hal_intrset(ah, 0); /* Stop new RX/TX completion */ @@ -5107,6 +5120,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS); sc->sc_beacons = 0; taskqueue_unblock(sc->sc_tq); + taskqueue_unblock(sc->sc_tx_tq); } ni = ieee80211_ref_node(vap->iv_bss); @@ -5272,6 +5286,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) "%s: calibration disabled\n", __func__); } taskqueue_unblock(sc->sc_tq); + taskqueue_unblock(sc->sc_tx_tq); } else if (nstate == IEEE80211_S_INIT) { /* * If there are no vaps left in RUN state then @@ -5285,6 +5300,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) /* disable interrupts */ ath_hal_intrset(ah, sc->sc_imask &~ HAL_INT_GLOBAL); taskqueue_block(sc->sc_tq); + taskqueue_block(sc->sc_tx_tq); sc->sc_beacons = 0; } #ifdef IEEE80211_SUPPORT_TDMA diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h index 39604c6..a97f897 100644 --- a/sys/dev/ath/if_ath_misc.h +++ b/sys/dev/ath/if_ath_misc.h @@ -125,7 +125,7 @@ ath_tx_kick(struct ath_softc *sc) { /* XXX eventually try sc_tx_tq? */ - taskqueue_enqueue(sc->sc_tq, &sc->sc_txpkttask); + taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txpkttask); } #endif diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index ad12fad..b3b6079 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -3001,7 +3001,7 @@ ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid) ath_tx_tid_sched(sc, tid); /* Punt some frames to the hardware if needed */ //ath_txq_sched(sc, sc->sc_ac2q[tid->ac]); - taskqueue_enqueue(sc->sc_tq, &sc->sc_txqtask); + taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask); } /* diff --git a/sys/dev/ath/if_ath_tx_edma.c b/sys/dev/ath/if_ath_tx_edma.c index 40a0378..a2eef65 100644 --- a/sys/dev/ath/if_ath_tx_edma.c +++ b/sys/dev/ath/if_ath_tx_edma.c @@ -655,7 +655,7 @@ ath_edma_tx_processq(struct ath_softc *sc, int dosched) * the txq task for _one_ TXQ. This should be fixed. */ if (dosched) - taskqueue_enqueue(sc->sc_tq, &sc->sc_txqtask); + taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask); } static void |