diff options
author | avos <avos@FreeBSD.org> | 2016-06-20 22:45:19 +0000 |
---|---|---|
committer | avos <avos@FreeBSD.org> | 2016-06-20 22:45:19 +0000 |
commit | 48e577c3c1612f3df3c7df33024a20dc49080b44 (patch) | |
tree | ad7ae7d39a100795c5afb1763d0b24322270a520 | |
parent | 39bab70fa61a7bb48f204c2cacbe2f14c50f942f (diff) | |
download | FreeBSD-src-48e577c3c1612f3df3c7df33024a20dc49080b44.zip FreeBSD-src-48e577c3c1612f3df3c7df33024a20dc49080b44.tar.gz |
rtwn: fix Tx processing, add some busdma synchronization.
1) Unload mbuf instead of descriptor in rtwn_tx_done().
2) Add more synchronization for device visible mappings before
touching the memory.
3) Improve watchdog timer logic.
Reported and tested by: mva
Approved by: re (gjb)
-rw-r--r-- | sys/dev/rtwn/if_rtwn.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c index 3ae0c1a..0a8f976 100644 --- a/sys/dev/rtwn/if_rtwn.c +++ b/sys/dev/rtwn/if_rtwn.c @@ -586,6 +586,9 @@ rtwn_free_rx_list(struct rtwn_softc *sc) if (rx_ring->desc_dmat != NULL) { if (rx_ring->desc != NULL) { + bus_dmamap_sync(rx_ring->desc_dmat, + rx_ring->desc_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(rx_ring->desc_dmat, rx_ring->desc_map); bus_dmamem_free(rx_ring->desc_dmat, rx_ring->desc, @@ -600,6 +603,8 @@ rtwn_free_rx_list(struct rtwn_softc *sc) rx_data = &rx_ring->rx_data[i]; if (rx_data->m != NULL) { + bus_dmamap_sync(rx_ring->data_dmat, + rx_data->map, BUS_DMASYNC_POSTREAD); bus_dmamap_unload(rx_ring->data_dmat, rx_data->map); m_freem(rx_data->m); rx_data->m = NULL; @@ -643,6 +648,8 @@ rtwn_alloc_tx_list(struct rtwn_softc *sc, int qid) device_printf(sc->sc_dev, "could not load desc DMA map\n"); goto fail; } + bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map, + BUS_DMASYNC_PREWRITE); error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, @@ -691,6 +698,8 @@ rtwn_reset_tx_list(struct rtwn_softc *sc, int qid) sizeof(desc->nextdescaddr))); if (tx_data->m != NULL) { + bus_dmamap_sync(tx_ring->data_dmat, tx_data->map, + BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(tx_ring->data_dmat, tx_data->map); m_freem(tx_data->m); tx_data->m = NULL; @@ -718,6 +727,8 @@ rtwn_free_tx_list(struct rtwn_softc *sc, int qid) if (tx_ring->desc_dmat != NULL) { if (tx_ring->desc != NULL) { + bus_dmamap_sync(tx_ring->desc_dmat, + tx_ring->desc_map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(tx_ring->desc_dmat, tx_ring->desc_map); bus_dmamem_free(tx_ring->desc_dmat, tx_ring->desc, @@ -730,6 +741,8 @@ rtwn_free_tx_list(struct rtwn_softc *sc, int qid) tx_data = &tx_ring->tx_data[i]; if (tx_data->m != NULL) { + bus_dmamap_sync(tx_ring->data_dmat, tx_data->map, + BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(tx_ring->data_dmat, tx_data->map); m_freem(tx_data->m); tx_data->m = NULL; @@ -1761,7 +1774,10 @@ rtwn_tx_done(struct rtwn_softc *sc, int qid) if (le32toh(tx_desc->txdw0) & R92C_TXDW0_OWN) continue; - bus_dmamap_unload(tx_ring->desc_dmat, tx_ring->desc_map); + /* Unmap and free mbuf. */ + bus_dmamap_sync(tx_ring->data_dmat, tx_data->map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(tx_ring->data_dmat, tx_data->map); /* * XXX TODO: figure out whether the transmit succeeded or not. @@ -1771,8 +1787,10 @@ rtwn_tx_done(struct rtwn_softc *sc, int qid) tx_data->ni = NULL; tx_data->m = NULL; - sc->sc_tx_timer = 0; - tx_ring->queued--; + if (--tx_ring->queued) + sc->sc_tx_timer = 5; + else + sc->sc_tx_timer = 0; } if (tx_ring->queued < (RTWN_TX_LIST_COUNT - 1)) |