summaryrefslogtreecommitdiffstats
path: root/sys/pci
diff options
context:
space:
mode:
authormux <mux@FreeBSD.org>2003-02-18 18:50:54 +0000
committermux <mux@FreeBSD.org>2003-02-18 18:50:54 +0000
commitd0626528fb759910b36578f9a641dfe8a76aa8a5 (patch)
treefd960312e300416c019c65c951feb33a2c98eeff /sys/pci
parent0006bd27309c961166c11265c90abdea81ad2cd3 (diff)
downloadFreeBSD-src-d0626528fb759910b36578f9a641dfe8a76aa8a5.zip
FreeBSD-src-d0626528fb759910b36578f9a641dfe8a76aa8a5.tar.gz
- Fix mbuf leak when we successfully allocate a new mbuf but fail to
bus_dmamap_load() it. - Make it so reusing mbufs when we can't allocate (or map) new ones actually works. We were previously trying to reuse a mbuf which was already bus_dmamap_unload()'ed. Reviewed by: silby
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/if_xl.c23
-rw-r--r--sys/pci/if_xlreg.h1
2 files changed, 18 insertions, 6 deletions
diff --git a/sys/pci/if_xl.c b/sys/pci/if_xl.c
index ead2e9c..c267188 100644
--- a/sys/pci/if_xl.c
+++ b/sys/pci/if_xl.c
@@ -1893,6 +1893,10 @@ xl_list_rx_init(sc)
cd = &sc->xl_cdata;
ld = &sc->xl_ldata;
+ error = bus_dmamap_create(sc->xl_mtag, 0, &sc->xl_tmpmap);
+ if (error)
+ return(error);
+
for (i = 0; i < XL_RX_LIST_CNT; i++) {
cd->xl_rx_chain[i].xl_ptr = &ld->xl_rx_list[i];
error = bus_dmamap_create(sc->xl_mtag, 0,
@@ -1920,6 +1924,8 @@ xl_list_rx_init(sc)
/*
* Initialize an RX descriptor and attach an MBUF cluster.
+ * If we fail to do so, we need to leave the old mbuf and
+ * the old DMA map untouched so that it can be reused.
*/
static int
xl_newbuf(sc, c)
@@ -1927,6 +1933,7 @@ xl_newbuf(sc, c)
struct xl_chain_onefrag *c;
{
struct mbuf *m_new = NULL;
+ bus_dmamap_t map;
int error;
u_int32_t baddr;
@@ -1945,17 +1952,21 @@ xl_newbuf(sc, c)
/* Force longword alignment for packet payload. */
m_adj(m_new, ETHER_ALIGN);
- c->xl_mbuf = m_new;
- c->xl_ptr->xl_frag.xl_len = htole32(m_new->m_len | XL_LAST_FRAG);
- c->xl_ptr->xl_status = 0;
-
- error = bus_dmamap_load(sc->xl_mtag, c->xl_map, mtod(m_new, void *),
+ error = bus_dmamap_load(sc->xl_mtag, sc->xl_tmpmap, mtod(m_new, void *),
MCLBYTES, xl_dma_map_addr, &baddr, 0);
if (error) {
m_freem(m_new);
printf("xl%d: can't map mbuf (error %d)\n", sc->xl_unit, error);
return(error);
}
+
+ bus_dmamap_unload(sc->xl_mtag, c->xl_map);
+ map = c->xl_map;
+ c->xl_map = sc->xl_tmpmap;
+ sc->xl_tmpmap = map;
+ c->xl_mbuf = m_new;
+ c->xl_ptr->xl_frag.xl_len = htole32(m_new->m_len | XL_LAST_FRAG);
+ c->xl_ptr->xl_status = 0;
c->xl_ptr->xl_frag.xl_addr = htole32(baddr);
bus_dmamap_sync(sc->xl_mtag, c->xl_map, BUS_DMASYNC_PREREAD);
return(0);
@@ -2040,7 +2051,6 @@ again:
/* No errors; receive the packet. */
bus_dmamap_sync(sc->xl_mtag, cur_rx->xl_map,
BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(sc->xl_mtag, cur_rx->xl_map);
m = cur_rx->xl_mbuf;
total_len = le32toh(cur_rx->xl_ptr->xl_status) &
XL_RXSTAT_LENMASK;
@@ -3191,6 +3201,7 @@ xl_stop(sc)
sc->xl_cdata.xl_rx_chain[i].xl_mbuf = NULL;
}
}
+ bus_dmamap_destroy(sc->xl_mtag, sc->xl_tmpmap);
bzero(sc->xl_ldata.xl_rx_list, XL_RX_LIST_SZ);
/*
* Free the TX list buffers.
diff --git a/sys/pci/if_xlreg.h b/sys/pci/if_xlreg.h
index 0a5ce44..f4dadbd 100644
--- a/sys/pci/if_xlreg.h
+++ b/sys/pci/if_xlreg.h
@@ -584,6 +584,7 @@ struct xl_softc {
device_t xl_miibus;
struct xl_type *xl_info; /* 3Com adapter info */
bus_dma_tag_t xl_mtag;
+ bus_dmamap_t xl_tmpmap; /* spare DMA map */
u_int8_t xl_unit; /* interface number */
u_int8_t xl_type;
u_int32_t xl_xcvr;
OpenPOWER on IntegriCloud