summaryrefslogtreecommitdiff
path: root/sys/dev/ath/if_ath_rx_edma.c
diff options
context:
space:
mode:
authorAdrian Chadd <adrian@FreeBSD.org>2013-04-04 08:21:56 +0000
committerAdrian Chadd <adrian@FreeBSD.org>2013-04-04 08:21:56 +0000
commit8cc724d9be9be3db8f59374d6e848ae169695cc3 (patch)
tree6643d814b78fee5e7d71c16dee98e2950139b311 /sys/dev/ath/if_ath_rx_edma.c
parent7d5621c981f9f61a9063c963afb309fe200814de (diff)
Notes
Diffstat (limited to 'sys/dev/ath/if_ath_rx_edma.c')
-rw-r--r--sys/dev/ath/if_ath_rx_edma.c82
1 files changed, 47 insertions, 35 deletions
diff --git a/sys/dev/ath/if_ath_rx_edma.c b/sys/dev/ath/if_ath_rx_edma.c
index 7dd697439fc1..9d8bd31d4d8d 100644
--- a/sys/dev/ath/if_ath_rx_edma.c
+++ b/sys/dev/ath/if_ath_rx_edma.c
@@ -362,11 +362,10 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
/*
* Sync descriptor memory - this also syncs the buffer for us.
- *
* EDMA descriptors are in cached memory.
*/
bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
- BUS_DMASYNC_POSTREAD);
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
rs = &bf->bf_status.ds_rxstat;
bf->bf_rxstatus = ath_hal_rxprocdesc(ah, ds, bf->bf_daddr,
NULL, rs);
@@ -384,16 +383,17 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
/*
* Completed descriptor.
- *
- * In the future we'll call ath_rx_pkt(), but it first
- * has to be taught about EDMA RX queues (so it can
- * access sc_rxpending correctly.)
*/
DPRINTF(sc, ATH_DEBUG_EDMA_RX,
"%s: Q%d: completed!\n", __func__, qtype);
npkts++;
/*
+ * We've been synced already, so unmap.
+ */
+ bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
+
+ /*
* Remove the FIFO entry and place it on the completion
* queue.
*/
@@ -468,6 +468,7 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
struct ath_rx_status *rs;
int16_t nf;
ath_bufhead rxlist;
+ struct mbuf *m;
TAILQ_INIT(&rxlist);
@@ -492,12 +493,11 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
m_adj(bf->bf_m, sc->sc_rx_statuslen);
/* Handle the frame */
- /*
- * Note: this may or may not free bf->bf_m and sync/unmap
- * the frame.
- */
+
rs = &bf->bf_status.ds_rxstat;
- if (ath_rx_pkt(sc, rs, bf->bf_rxstatus, tsf, nf, qtype, bf))
+ m = bf->bf_m;
+ bf->bf_m = NULL;
+ if (ath_rx_pkt(sc, rs, bf->bf_rxstatus, tsf, nf, qtype, bf, m))
ngood++;
}
@@ -605,10 +605,27 @@ ath_edma_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
/*
+ * Populate ath_buf fields.
+ */
+ bf->bf_desc = mtod(m, struct ath_desc *);
+ bf->bf_lastds = bf->bf_desc; /* XXX only really for TX? */
+ bf->bf_m = m;
+
+ /*
+ * Zero the descriptor and ensure it makes it out to the
+ * bounce buffer if one is required.
+ *
+ * XXX PREWRITE will copy the whole buffer; we only needed it
+ * to sync the first 32 DWORDS. Oh well.
+ */
+ memset(bf->bf_desc, '\0', sc->sc_rx_statuslen);
+
+ /*
* Create DMA mapping.
*/
error = bus_dmamap_load_mbuf_sg(sc->sc_dmat,
bf->bf_dmamap, m, bf->bf_segs, &bf->bf_nseg, BUS_DMA_NOWAIT);
+
if (error != 0) {
device_printf(sc->sc_dev, "%s: failed; error=%d\n",
__func__,
@@ -618,30 +635,27 @@ ath_edma_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
}
/*
- * Populate ath_buf fields.
+ * Set daddr to the physical mapping page.
*/
-
- bf->bf_desc = mtod(m, struct ath_desc *);
bf->bf_daddr = bf->bf_segs[0].ds_addr;
- bf->bf_lastds = bf->bf_desc; /* XXX only really for TX? */
- bf->bf_m = m;
- /* Zero the descriptor */
- memset(bf->bf_desc, '\0', sc->sc_rx_statuslen);
-
-#if 0
/*
- * Adjust mbuf header and length/size to compensate for the
- * descriptor size.
+ * Prepare for the upcoming read.
+ *
+ * We need to both sync some data into the buffer (the zero'ed
+ * descriptor payload) and also prepare for the read that's going
+ * to occur.
*/
- m_adj(m, sc->sc_rx_statuslen);
-#endif
+ bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
/* Finish! */
-
return (0);
}
+/*
+ * Allocate a RX buffer.
+ */
static struct ath_buf *
ath_edma_rxbuf_alloc(struct ath_softc *sc)
{
@@ -653,8 +667,11 @@ ath_edma_rxbuf_alloc(struct ath_softc *sc)
/* Allocate buffer */
bf = TAILQ_FIRST(&sc->sc_rxbuf);
/* XXX shouldn't happen upon startup? */
- if (bf == NULL)
+ if (bf == NULL) {
+ device_printf(sc->sc_dev, "%s: nothing on rxbuf?!\n",
+ __func__);
return (NULL);
+ }
/* Remove it from the free list */
TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list);
@@ -743,18 +760,13 @@ ath_edma_rxfifo_alloc(struct ath_softc *sc, HAL_RX_QUEUE qtype, int nbufs)
re->m_fifo[re->m_fifo_tail] = bf;
- /*
- * Flush the descriptor contents before it's handed to the
- * hardware.
- */
- bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
- BUS_DMASYNC_PREREAD);
-
/* Write to the RX FIFO */
- DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: Q%d: putrxbuf=%p\n",
+ DPRINTF(sc, ATH_DEBUG_EDMA_RX,
+ "%s: Q%d: putrxbuf=%p (0x%jx)\n",
__func__,
qtype,
- bf->bf_desc);
+ bf->bf_desc,
+ (uintmax_t) bf->bf_daddr);
ath_hal_putrxbuf(sc->sc_ah, bf->bf_daddr, qtype);
re->m_fifo_depth++;