summaryrefslogtreecommitdiffstats
path: root/sys/dev/rtwn
diff options
context:
space:
mode:
authoravos <avos@FreeBSD.org>2016-06-20 22:45:19 +0000
committeravos <avos@FreeBSD.org>2016-06-20 22:45:19 +0000
commit48e577c3c1612f3df3c7df33024a20dc49080b44 (patch)
treead7ae7d39a100795c5afb1763d0b24322270a520 /sys/dev/rtwn
parent39bab70fa61a7bb48f204c2cacbe2f14c50f942f (diff)
downloadFreeBSD-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)
Diffstat (limited to 'sys/dev/rtwn')
-rw-r--r--sys/dev/rtwn/if_rtwn.c24
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))
OpenPOWER on IntegriCloud