diff options
author | bschmidt <bschmidt@FreeBSD.org> | 2010-12-30 18:29:22 +0000 |
---|---|---|
committer | bschmidt <bschmidt@FreeBSD.org> | 2010-12-30 18:29:22 +0000 |
commit | 543d6f8f19d01a1c2b2c7ae511afd03acf3176d2 (patch) | |
tree | f3836dc3d1d3d56285c300a054d76d4b58925b5c | |
parent | 7a575413cdc4c11c26f5d9578b5458a6cbaecdbd (diff) | |
download | FreeBSD-src-543d6f8f19d01a1c2b2c7ae511afd03acf3176d2.zip FreeBSD-src-543d6f8f19d01a1c2b2c7ae511afd03acf3176d2.tar.gz |
The RX path is missing a few bus_dmamap_*() calls, this results in
modification of memory which was already free'd and eventually in:
wpi0: could not map mbuf (error 12)
wpi0: wpi_rx_intr: bus_dmamap_load failed, error 12
and an usuable device.
PR: kern/144898
MFC after: 3 days
-rw-r--r-- | sys/dev/wpi/if_wpi.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c index b4f94e0..b68451d 100644 --- a/sys/dev/wpi/if_wpi.c +++ b/sys/dev/wpi/if_wpi.c @@ -1052,9 +1052,18 @@ wpi_free_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring) wpi_dma_contig_free(&ring->desc_dma); - for (i = 0; i < WPI_RX_RING_COUNT; i++) - if (ring->data[i].m != NULL) - m_freem(ring->data[i].m); + for (i = 0; i < WPI_RX_RING_COUNT; i++) { + struct wpi_rx_data *data = &ring->data[i]; + + if (data->m != NULL) { + bus_dmamap_sync(ring->data_dmat, data->map, + BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(ring->data_dmat, data->map); + m_freem(data->m); + } + if (data->map != NULL) + bus_dmamap_destroy(ring->data_dmat, data->map); + } } static int @@ -1461,6 +1470,7 @@ wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc, return; } + bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); head = (struct wpi_rx_head *)((caddr_t)(stat + 1) + stat->len); tail = (struct wpi_rx_tail *)((caddr_t)(head + 1) + le16toh(head->len)); @@ -1491,6 +1501,8 @@ wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc, ifp->if_ierrors++; return; } + bus_dmamap_unload(ring->data_dmat, data->map); + error = bus_dmamap_load(ring->data_dmat, data->map, mtod(mnew, caddr_t), MJUMPAGESIZE, wpi_dma_map_addr, &paddr, BUS_DMA_NOWAIT); |