diff options
Diffstat (limited to 'sys/dev/ath/if_ath_rx_edma.c')
-rw-r--r-- | sys/dev/ath/if_ath_rx_edma.c | 175 |
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; |