diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 965a1fd6c07..650efbe9a5b 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -2888,6 +2888,67 @@ fail0: #undef ATH_DESC_4KB_BOUND_CHECK } +/* + * Allocate ath_buf entries but no descriptor contents. + * + * This is for RX EDMA where the descriptors are the header part of + * the RX buffer. + */ +int +ath_descdma_setup_rx_edma(struct ath_softc *sc, + struct ath_descdma *dd, ath_bufhead *head, + const char *name, int nbuf, int rx_status_len) +{ + struct ifnet *ifp = sc->sc_ifp; + struct ath_buf *bf; + int i, bsize, error; + + DPRINTF(sc, ATH_DEBUG_RESET, "%s: %s DMA: %u buffers\n", + __func__, name, nbuf); + + dd->dd_name = name; + /* + * This is (mostly) purely for show. We're not allocating any actual + * descriptors here as EDMA RX has the descriptor be part + * of the RX buffer. + * + * However, dd_desc_len is used by ath_descdma_free() to determine + * whether we have already freed this DMA mapping. + */ + dd->dd_desc_len = rx_status_len; + + /* allocate rx buffers */ + bsize = sizeof(struct ath_buf) * nbuf; + bf = malloc(bsize, M_ATHDEV, M_NOWAIT | M_ZERO); + if (bf == NULL) { + if_printf(ifp, "malloc of %s buffers failed, size %u\n", + dd->dd_name, bsize); + goto fail3; + } + dd->dd_bufptr = bf; + + TAILQ_INIT(head); + for (i = 0; i < nbuf; i++, bf++) { + bf->bf_desc = NULL; + bf->bf_daddr = 0; + bf->bf_lastds = NULL; /* Just an initial value */ + + error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT, + &bf->bf_dmamap); + if (error != 0) { + if_printf(ifp, "unable to create dmamap for %s " + "buffer %u, error %u\n", dd->dd_name, i, error); + ath_descdma_cleanup(sc, dd, head); + return error; + } + TAILQ_INSERT_TAIL(head, bf, bf_list); + } + return 0; +fail3: + memset(dd, 0, sizeof(*dd)); + return error; +} + void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, ath_bufhead *head) diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h index 0a51feeec76..23c9f68fc64 100644 --- a/sys/dev/ath/if_ath_misc.h +++ b/sys/dev/ath/if_ath_misc.h @@ -86,6 +86,9 @@ extern void ath_setslottime(struct ath_softc *sc); extern int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, ath_bufhead *head, const char *name, int nbuf, int ndesc); +extern int ath_descdma_setup_rx_edma(struct ath_softc *sc, + struct ath_descdma *dd, ath_bufhead *head, const char *name, + int nbuf, int desclen); extern void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, ath_bufhead *head); diff --git a/sys/dev/ath/if_ath_rx_edma.c b/sys/dev/ath/if_ath_rx_edma.c index 9e3580d966c..9ed3a91afa3 100644 --- a/sys/dev/ath/if_ath_rx_edma.c +++ b/sys/dev/ath/if_ath_rx_edma.c @@ -696,11 +696,11 @@ ath_edma_dma_rxsetup(struct ath_softc *sc) { int error; - /* Create RX DMA tag */ - /* Create RX ath_buf array */ - - error = ath_descdma_setup(sc, &sc->sc_rxdma, &sc->sc_rxbuf, - "rx", ath_rxbuf, 1); + /* + * Create RX DMA tag and buffers. + */ + error = ath_descdma_setup_rx_edma(sc, &sc->sc_rxdma, &sc->sc_rxbuf, + "rx", ath_rxbuf, sc->sc_rx_statuslen); if (error != 0) return error; @@ -739,15 +739,16 @@ ath_recv_setup_edma(struct ath_softc *sc) /* Set buffer size to 4k */ sc->sc_edma_bufsize = 4096; - /* Configure the hardware with this */ - (void) ath_hal_setrxbufsize(sc->sc_ah, sc->sc_edma_bufsize); - /* Fetch EDMA field and buffer sizes */ (void) ath_hal_getrxstatuslen(sc->sc_ah, &sc->sc_rx_statuslen); (void) ath_hal_gettxdesclen(sc->sc_ah, &sc->sc_tx_desclen); (void) ath_hal_gettxstatuslen(sc->sc_ah, &sc->sc_tx_statuslen); (void) ath_hal_getntxmaps(sc->sc_ah, &sc->sc_tx_nmaps); + /* Configure the hardware with the RX buffer size */ + (void) ath_hal_setrxbufsize(sc->sc_ah, sc->sc_edma_bufsize - + sc->sc_rx_statuslen); + device_printf(sc->sc_dev, "RX status length: %d\n", sc->sc_rx_statuslen); device_printf(sc->sc_dev, "TX descriptor length: %d\n",