svn commit: r301845 - head/sys/dev/iwm
Adrian Chadd
adrian at FreeBSD.org
Mon Jun 13 00:13:21 UTC 2016
Author: adrian
Date: Mon Jun 13 00:13:20 2016
New Revision: 301845
URL: https://svnweb.freebsd.org/changeset/base/301845
Log:
[iwm] Fix up busdma use in the RX path
When allocating a new mbuf or bus_dmamap_load()-ing it fails,
we can just keep the old mbuf since we are dropping that packet anyway.
Instead of doing bus_dmamap_create() and bus_dmamap_destroy() all the time,
create an extra bus_dmamap_t which we can use to safely try
bus_dmamap_load()-ing the new mbuf. On success we just swap the spare
bus_dmamap_t with the data->map of that ring entry.
Tested:
Tested with Intel AC7260, verified with vmstat -m that new kernel no
longer visibly leaks memory from the M_DEVBUF malloc type.
Before, leakage was 1KB every few seconds while ping(8)-ing over the wlan
connection.
Submitted by: Imre Vadasz <imre at vdsz.com>
Approved by: re@
Obtained from: DragonflyBSD.git cc440b26818b5dfdd9af504d71c1b0e6522b53ef
Differential Revision: https://reviews.freebsd.org/D6742
Modified:
head/sys/dev/iwm/if_iwm.c
head/sys/dev/iwm/if_iwmvar.h
Modified: head/sys/dev/iwm/if_iwm.c
==============================================================================
--- head/sys/dev/iwm/if_iwm.c Mon Jun 13 00:03:55 2016 (r301844)
+++ head/sys/dev/iwm/if_iwm.c Mon Jun 13 00:13:20 2016 (r301845)
@@ -866,10 +866,28 @@ iwm_alloc_rx_ring(struct iwm_softc *sc,
goto fail;
}
+ /* Allocate spare bus_dmamap_t for iwm_rx_addbuf() */
+ error = bus_dmamap_create(ring->data_dmat, 0, &ring->spare_map);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not create RX buf DMA map, error %d\n",
+ __func__, error);
+ goto fail;
+ }
/*
* Allocate and map RX buffers.
*/
for (i = 0; i < IWM_RX_RING_COUNT; i++) {
+ struct iwm_rx_data *data = &ring->data[i];
+ error = bus_dmamap_create(ring->data_dmat, 0, &data->map);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not create RX buf DMA map, error %d\n",
+ __func__, error);
+ goto fail;
+ }
+ data->m = NULL;
+
if ((error = iwm_rx_addbuf(sc, IWM_RBUF_SIZE, i)) != 0) {
goto fail;
}
@@ -923,6 +941,10 @@ iwm_free_rx_ring(struct iwm_softc *sc, s
data->map = NULL;
}
}
+ if (ring->spare_map != NULL) {
+ bus_dmamap_destroy(ring->data_dmat, ring->spare_map);
+ ring->spare_map = NULL;
+ }
if (ring->data_dmat != NULL) {
bus_dma_tag_destroy(ring->data_dmat);
ring->data_dmat = NULL;
@@ -2119,6 +2141,7 @@ iwm_rx_addbuf(struct iwm_softc *sc, int
struct iwm_rx_ring *ring = &sc->rxq;
struct iwm_rx_data *data = &ring->data[idx];
struct mbuf *m;
+ bus_dmamap_t dmamap = NULL;
int error;
bus_addr_t paddr;
@@ -2126,28 +2149,26 @@ iwm_rx_addbuf(struct iwm_softc *sc, int
if (m == NULL)
return ENOBUFS;
- if (data->m != NULL)
- bus_dmamap_unload(ring->data_dmat, data->map);
-
m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
- error = bus_dmamap_create(ring->data_dmat, 0, &data->map);
- if (error != 0) {
- device_printf(sc->sc_dev,
- "%s: could not create RX buf DMA map, error %d\n",
- __func__, error);
- goto fail;
- }
- data->m = m;
- error = bus_dmamap_load(ring->data_dmat, data->map,
- mtod(data->m, void *), IWM_RBUF_SIZE, iwm_dma_map_addr,
+ error = bus_dmamap_load(ring->data_dmat, ring->spare_map,
+ mtod(m, void *), IWM_RBUF_SIZE, iwm_dma_map_addr,
&paddr, BUS_DMA_NOWAIT);
if (error != 0 && error != EFBIG) {
device_printf(sc->sc_dev,
- "%s: can't not map mbuf, error %d\n", __func__,
- error);
+ "%s: can't map mbuf, error %d\n", __func__, error);
goto fail;
}
+
+ if (data->m != NULL)
+ bus_dmamap_unload(ring->data_dmat, data->map);
+
+ /* Swap ring->spare_map with data->map */
+ dmamap = data->map;
+ data->map = ring->spare_map;
+ ring->spare_map = dmamap;
+
bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREREAD);
+ data->m = m;
/* Update RX descriptor. */
ring->desc[idx] = htole32(paddr >> 8);
@@ -2156,6 +2177,7 @@ iwm_rx_addbuf(struct iwm_softc *sc, int
return 0;
fail:
+ m_free(m);
return error;
}
Modified: head/sys/dev/iwm/if_iwmvar.h
==============================================================================
--- head/sys/dev/iwm/if_iwmvar.h Mon Jun 13 00:03:55 2016 (r301844)
+++ head/sys/dev/iwm/if_iwmvar.h Mon Jun 13 00:13:20 2016 (r301845)
@@ -289,6 +289,7 @@ struct iwm_rx_ring {
uint32_t *desc;
struct iwm_rb_status *stat;
struct iwm_rx_data data[IWM_RX_RING_COUNT];
+ bus_dmamap_t spare_map; /* for iwm_rx_addbuf() */
bus_dma_tag_t data_dmat;
int cur;
};
More information about the svn-src-head
mailing list