summaryrefslogtreecommitdiffstats
path: root/sys/dev/ath/if_ath_rx_edma.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ath/if_ath_rx_edma.c')
-rw-r--r--sys/dev/ath/if_ath_rx_edma.c175
1 files changed, 55 insertions, 120 deletions
diff --git a/sys/dev/ath/if_ath_rx_edma.c b/sys/dev/ath/if_ath_rx_edma.c
index 7aa818f..2be8627 100644
--- a/sys/dev/ath/if_ath_rx_edma.c
+++ b/sys/dev/ath/if_ath_rx_edma.c
@@ -73,7 +73,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <net/if.h>
-#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -160,20 +159,10 @@ ath_edma_stoprecv(struct ath_softc *sc, int dodelay)
struct ath_hal *ah = sc->sc_ah;
ATH_RX_LOCK(sc);
-
ath_hal_stoppcurecv(ah);
ath_hal_setrxfilter(ah, 0);
+ ath_hal_stopdmarecv(ah);
- /*
- *
- */
- if (ath_hal_stopdmarecv(ah) == AH_TRUE)
- sc->sc_rx_stopped = 1;
-
- /*
- * Give the various bus FIFOs (not EDMA descriptor FIFO)
- * time to finish flushing out data.
- */
DELAY(3000);
/* Flush RX pending for each queue */
@@ -228,6 +217,10 @@ ath_edma_reinit_fifo(struct ath_softc *sc, HAL_RX_QUEUE qtype)
/*
* Start receive.
+ *
+ * XXX TODO: this needs to reallocate the FIFO entries when a reset
+ * occurs, in case the FIFO is filled up and no new descriptors get
+ * thrown into the FIFO.
*/
static int
ath_edma_startrecv(struct ath_softc *sc)
@@ -236,31 +229,35 @@ ath_edma_startrecv(struct ath_softc *sc)
ATH_RX_LOCK(sc);
- /*
- * Sanity check - are we being called whilst RX
- * isn't stopped? If so, we may end up pushing
- * too many entries into the RX FIFO and
- * badness occurs.
- */
-
/* Enable RX FIFO */
ath_hal_rxena(ah);
/*
- * In theory the hardware has been initialised, right?
+ * Entries should only be written out if the
+ * FIFO is empty.
+ *
+ * XXX This isn't correct. I should be looking
+ * at the value of AR_RXDP_SIZE (0x0070) to determine
+ * how many entries are in here.
+ *
+ * A warm reset will clear the registers but not the FIFO.
+ *
+ * And I believe this is actually the address of the last
+ * handled buffer rather than the current FIFO pointer.
+ * So if no frames have been (yet) seen, we'll reinit the
+ * FIFO.
+ *
+ * I'll chase that up at some point.
*/
- if (sc->sc_rx_resetted == 1) {
+ if (ath_hal_getrxbuf(sc->sc_ah, HAL_RX_QUEUE_HP) == 0) {
DPRINTF(sc, ATH_DEBUG_EDMA_RX,
"%s: Re-initing HP FIFO\n", __func__);
ath_edma_reinit_fifo(sc, HAL_RX_QUEUE_HP);
+ }
+ if (ath_hal_getrxbuf(sc->sc_ah, HAL_RX_QUEUE_LP) == 0) {
DPRINTF(sc, ATH_DEBUG_EDMA_RX,
"%s: Re-initing LP FIFO\n", __func__);
ath_edma_reinit_fifo(sc, HAL_RX_QUEUE_LP);
- sc->sc_rx_resetted = 0;
- } else {
- device_printf(sc->sc_dev,
- "%s: called without resetting chip?\n",
- __func__);
}
/* Add up to m_fifolen entries in each queue */
@@ -268,9 +265,6 @@ ath_edma_startrecv(struct ath_softc *sc)
* These must occur after the above write so the FIFO buffers
* are pushed/tracked in the same order as the hardware will
* process them.
- *
- * XXX TODO: is this really necessary? We should've stopped
- * the hardware already and reinitialised it, so it's a no-op.
*/
ath_edma_rxfifo_alloc(sc, HAL_RX_QUEUE_HP,
sc->sc_rxedma[HAL_RX_QUEUE_HP].m_fifolen);
@@ -281,11 +275,6 @@ ath_edma_startrecv(struct ath_softc *sc)
ath_mode_init(sc);
ath_hal_startpcurecv(ah);
- /*
- * We're now doing RX DMA!
- */
- sc->sc_rx_stopped = 0;
-
ATH_RX_UNLOCK(sc);
return (0);
@@ -296,16 +285,7 @@ ath_edma_recv_sched_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
int dosched)
{
- ATH_LOCK(sc);
- ath_power_set_power_state(sc, HAL_PM_AWAKE);
- ATH_UNLOCK(sc);
-
ath_edma_recv_proc_queue(sc, qtype, dosched);
-
- ATH_LOCK(sc);
- ath_power_restore_power_state(sc);
- ATH_UNLOCK(sc);
-
taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask);
}
@@ -313,17 +293,8 @@ static void
ath_edma_recv_sched(struct ath_softc *sc, int dosched)
{
- ATH_LOCK(sc);
- ath_power_set_power_state(sc, HAL_PM_AWAKE);
- ATH_UNLOCK(sc);
-
ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_HP, dosched);
ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_LP, dosched);
-
- ATH_LOCK(sc);
- ath_power_restore_power_state(sc);
- ATH_UNLOCK(sc);
-
taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask);
}
@@ -337,10 +308,6 @@ ath_edma_recv_flush(struct ath_softc *sc)
sc->sc_rxproc_cnt++;
ATH_PCU_UNLOCK(sc);
- ATH_LOCK(sc);
- ath_power_set_power_state(sc, HAL_PM_AWAKE);
- ATH_UNLOCK(sc);
-
/*
* Flush any active frames from FIFO -> deferred list
*/
@@ -350,18 +317,9 @@ ath_edma_recv_flush(struct ath_softc *sc)
/*
* Process what's in the deferred queue
*/
- /*
- * XXX: If we read the tsf/channoise here and then pass it in,
- * we could restore the power state before processing
- * the deferred queue.
- */
ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_HP, 0);
ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_LP, 0);
- ATH_LOCK(sc);
- ath_power_restore_power_state(sc);
- ATH_UNLOCK(sc);
-
ATH_PCU_LOCK(sc);
sc->sc_rxproc_cnt--;
ATH_PCU_UNLOCK(sc);
@@ -390,21 +348,6 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
ATH_RX_LOCK(sc);
-#if 1
- if (sc->sc_rx_resetted == 1) {
- /*
- * XXX We shouldn't ever be scheduled if
- * receive has been stopped - so complain
- * loudly!
- */
- device_printf(sc->sc_dev,
- "%s: sc_rx_resetted=1! Bad!\n",
- __func__);
- ATH_RX_UNLOCK(sc);
- return;
- }
-#endif
-
do {
bf = re->m_fifo[re->m_fifo_head];
/* This shouldn't occur! */
@@ -476,6 +419,24 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
"ath edma rx proc: npkts=%d\n",
npkts);
+ /* Handle resched and kickpcu appropriately */
+ ATH_PCU_LOCK(sc);
+ if (dosched && sc->sc_kickpcu) {
+ ATH_KTR(sc, ATH_KTR_ERROR, 0,
+ "ath_edma_recv_proc_queue(): kickpcu");
+ if (npkts > 0)
+ device_printf(sc->sc_dev,
+ "%s: handled npkts %d\n",
+ __func__, npkts);
+
+ /*
+ * XXX TODO: what should occur here? Just re-poke and
+ * re-enable the RX FIFO?
+ */
+ sc->sc_kickpcu = 0;
+ }
+ ATH_PCU_UNLOCK(sc);
+
return;
}
@@ -488,20 +449,18 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
static void
ath_edma_flush_deferred_queue(struct ath_softc *sc)
{
- struct ath_buf *bf;
+ struct ath_buf *bf, *next;
ATH_RX_LOCK_ASSERT(sc);
/* Free in one set, inside the lock */
- while (! TAILQ_EMPTY(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP])) {
- bf = TAILQ_FIRST(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP]);
- TAILQ_REMOVE(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP], bf, bf_list);
+ TAILQ_FOREACH_SAFE(bf,
+ &sc->sc_rx_rxlist[HAL_RX_QUEUE_LP], bf_list, next) {
/* Free the buffer/mbuf */
ath_edma_rxbuf_free(sc, bf);
}
- while (! TAILQ_EMPTY(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP])) {
- bf = TAILQ_FIRST(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP]);
- TAILQ_REMOVE(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP], bf, bf_list);
+ TAILQ_FOREACH_SAFE(bf,
+ &sc->sc_rx_rxlist[HAL_RX_QUEUE_HP], bf_list, next) {
/* Free the buffer/mbuf */
ath_edma_rxbuf_free(sc, bf);
}
@@ -535,10 +494,6 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
ATH_RX_UNLOCK(sc);
/* Handle the completed descriptors */
- /*
- * XXX is this SAFE call needed? The ath_buf entries
- * aren't modified by ath_rx_pkt, right?
- */
TAILQ_FOREACH_SAFE(bf, &rxlist, bf_list, next) {
/*
* Skip the RX descriptor status - start at the data offset
@@ -564,9 +519,7 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
/* Free in one set, inside the lock */
ATH_RX_LOCK(sc);
- while (! TAILQ_EMPTY(&rxlist)) {
- bf = TAILQ_FIRST(&rxlist);
- TAILQ_REMOVE(&rxlist, bf, bf_list);
+ TAILQ_FOREACH_SAFE(bf, &rxlist, bf_list, next) {
/* Free the buffer/mbuf */
ath_edma_rxbuf_free(sc, bf);
}
@@ -598,25 +551,12 @@ ath_edma_recv_tasklet(void *arg, int npending)
sc->sc_rxproc_cnt++;
ATH_PCU_UNLOCK(sc);
- ATH_LOCK(sc);
- ath_power_set_power_state(sc, HAL_PM_AWAKE);
- ATH_UNLOCK(sc);
-
ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_HP, 1);
ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_LP, 1);
ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_HP, 1);
ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_LP, 1);
- /*
- * XXX: If we read the tsf/channoise here and then pass it in,
- * we could restore the power state before processing
- * the deferred queue.
- */
- ATH_LOCK(sc);
- ath_power_restore_power_state(sc);
- ATH_UNLOCK(sc);
-
/* XXX inside IF_LOCK ? */
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
#ifdef IEEE80211_SUPPORT_SUPERG
@@ -895,13 +835,10 @@ ath_edma_setup_rxfifo(struct ath_softc *sc, HAL_RX_QUEUE qtype)
qtype);
return (-EINVAL);
}
-
- if (bootverbose)
- device_printf(sc->sc_dev,
- "%s: type=%d, FIFO depth = %d entries\n",
- __func__,
- qtype,
- re->m_fifolen);
+ device_printf(sc->sc_dev, "%s: type=%d, FIFO depth = %d entries\n",
+ __func__,
+ qtype,
+ re->m_fifolen);
/* Allocate ath_buf FIFO array, pre-zero'ed */
re->m_fifo = malloc(sizeof(struct ath_buf *) * re->m_fifolen,
@@ -992,12 +929,10 @@ ath_recv_setup_edma(struct ath_softc *sc)
(void) ath_hal_setrxbufsize(sc->sc_ah, sc->sc_edma_bufsize -
sc->sc_rx_statuslen);
- if (bootverbose) {
- device_printf(sc->sc_dev, "RX status length: %d\n",
- sc->sc_rx_statuslen);
- device_printf(sc->sc_dev, "RX buffer size: %d\n",
- sc->sc_edma_bufsize);
- }
+ device_printf(sc->sc_dev, "RX status length: %d\n",
+ sc->sc_rx_statuslen);
+ device_printf(sc->sc_dev, "RX buffer size: %d\n",
+ sc->sc_edma_bufsize);
sc->sc_rx.recv_stop = ath_edma_stoprecv;
sc->sc_rx.recv_start = ath_edma_startrecv;
OpenPOWER on IntegriCloud