[ath] Attempt to fix epoch handling.

The epoch stuff with taskqueues works fine if the driver never calls
the receive path in other contexts, but this driver does.  If there was
a chip reset during active receive then part of the reset will call
the receive path to flush out any active packets before reinitialising
the receive queue and that needs to be done with the epoch held.

So:

* make the receive task a normal task again
* explicitly call epoch enter/exit around the legacy and newer DMA
  receive paths
* add a couple of epoch asserts to ensure that the receive packet
  path itself is called with epoch held.

This fixes it on my Atom eeepc laptop (circa 2010!) that I did
all of my initial 802.11n work in this driver and net80211.

Tested:

* AR9285, STA mode

TODO:

* Test on EDMA chipset (AR9380)
* Test in AP/adhoc modes, just to be sure (eg for beacon
  receive processing in particular.)
This commit is contained in:
Adrian Chadd 2020-02-20 07:12:43 +00:00
parent f646d24c82
commit af2441fbc7
3 changed files with 15 additions and 2 deletions

View File

@ -760,7 +760,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
device_get_nameunit(sc->sc_dev));
NET_TASK_INIT(&sc->sc_rxtask, 0, sc->sc_rx.recv_tasklet, sc);
TASK_INIT(&sc->sc_rxtask, 0, sc->sc_rx.recv_tasklet, sc);
TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc);
TASK_INIT(&sc->sc_bstucktask,0, ath_bstuck_proc, sc);
TASK_INIT(&sc->sc_resettask,0, ath_reset_proc, sc);

View File

@ -656,6 +656,8 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
int is_good = 0;
struct ath_rx_edma *re = &sc->sc_rxedma[qtype];
NET_EPOCH_ASSERT();
/*
* Calculate the correct 64 bit TSF given
* the TSF64 register value and rs_tstamp.
@ -1074,6 +1076,8 @@ ath_rx_proc(struct ath_softc *sc, int resched)
int kickpcu = 0;
int ret;
NET_EPOCH_ASSERT();
/* XXX we must not hold the ATH_LOCK here */
ATH_UNLOCK_ASSERT(sc);
ATH_PCU_UNLOCK_ASSERT(sc);
@ -1293,6 +1297,7 @@ static void
ath_legacy_rx_tasklet(void *arg, int npending)
{
struct ath_softc *sc = arg;
struct epoch_tracker et;
ATH_KTR(sc, ATH_KTR_RXPROC, 1, "ath_rx_proc: pending=%d", npending);
DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: pending %u\n", __func__, npending);
@ -1305,14 +1310,18 @@ ath_legacy_rx_tasklet(void *arg, int npending)
}
ATH_PCU_UNLOCK(sc);
NET_EPOCH_ENTER(et);
ath_rx_proc(sc, 1);
NET_EPOCH_EXIT(et);
}
static void
ath_legacy_flushrecv(struct ath_softc *sc)
{
struct epoch_tracker et;
NET_EPOCH_ENTER(et);
ath_rx_proc(sc, 0);
NET_EPOCH_EXIT(et);
}
static void

View File

@ -521,6 +521,7 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
int16_t nf;
ath_bufhead rxlist;
struct mbuf *m;
struct epoch_tracker et;
TAILQ_INIT(&rxlist);
@ -537,6 +538,8 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
TAILQ_CONCAT(&rxlist, &sc->sc_rx_rxlist[qtype], bf_list);
ATH_RX_UNLOCK(sc);
NET_EPOCH_ENTER(et);
/* Handle the completed descriptors */
/*
* XXX is this SAFE call needed? The ath_buf entries
@ -560,6 +563,7 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
if (ngood) {
sc->sc_lastrx = tsf;
}
NET_EPOCH_EXIT(et);
ATH_KTR(sc, ATH_KTR_INTERRUPTS, 1,
"ath edma rx deferred proc: ngood=%d\n",