From 1ebfdbf5a83e6ba979abe7b113cd34e72c43c40f Mon Sep 17 00:00:00 2001 From: Michal Hajduk Date: Tue, 22 Sep 2009 12:24:48 +0200 Subject: [PATCH 3/5] mge: Fix mge dma free after error. --- sys/dev/mge/if_mge.c | 58 +++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 50 insertions(+), 8 deletions(-) diff --git a/sys/dev/mge/if_mge.c b/sys/dev/mge/if_mge.c index a1431d6..fb22c52 100644 --- a/sys/dev/mge/if_mge.c +++ b/sys/dev/mge/if_mge.c @@ -371,13 +371,16 @@ mge_new_rxbuf(bus_dma_tag_t tag, bus_dmamap_t map, struct mbuf **mbufp, error = bus_dmamap_load_mbuf_sg(tag, map, new_mbuf, seg, &nsegs, BUS_DMA_NOWAIT); KASSERT(nsegs == 1, ("Too many segments returned!")); - if (nsegs != 1 || error) - panic("mge_new_rxbuf(): nsegs(%d), error(%d)", nsegs, error); + if (nsegs != 1 || error) { + m_freem(new_mbuf); + return (ENXIO); + } bus_dmamap_sync(tag, map, BUS_DMASYNC_PREREAD); (*mbufp) = new_mbuf; (*paddr) = seg->ds_addr; + return (0); } @@ -472,23 +475,62 @@ mge_allocate_dma(struct mge_softc *sc) sizeof(struct mge_desc), 0, /* maxsegsz, flags */ NULL, NULL, /* lockfunc, lockfuncarg */ &sc->mge_desc_dtag); /* dmat */ + if (error) { + device_printf(sc->dev, "could not create bus dma tag\n"); + return (ENXIO); + } - - mge_alloc_desc_dma(sc, sc->mge_tx_desc, MGE_TX_DESC_NUM, + error = mge_alloc_desc_dma(sc, sc->mge_tx_desc, MGE_TX_DESC_NUM, &sc->mge_tx_dtag); - mge_alloc_desc_dma(sc, sc->mge_rx_desc, MGE_RX_DESC_NUM, + if (error) { + device_printf(sc->dev, "could not alloc DMA TX desc\n"); + goto error; + } + + error = mge_alloc_desc_dma(sc, sc->mge_rx_desc, MGE_RX_DESC_NUM, &sc->mge_rx_dtag); + if (error) { + device_printf(sc->dev, "could not alloc DMA RX desc\n"); + goto error; + } for (i = 0; i < MGE_RX_DESC_NUM; i++) { dw = &(sc->mge_rx_desc[i]); - mge_new_rxbuf(sc->mge_rx_dtag, dw->buffer_dmap, &dw->buffer, + error = mge_new_rxbuf(sc->mge_rx_dtag, dw->buffer_dmap, &dw->buffer, &dw->mge_desc->buffer); + if (error) + goto error; } sc->tx_desc_start = sc->mge_tx_desc[0].mge_desc_paddr; sc->rx_desc_start = sc->mge_rx_desc[0].mge_desc_paddr; return (0); + +error: + for (i = 0; i < MGE_RX_DESC_NUM; i++) { + dw = &(sc->mge_rx_desc[i]); + if (dw->buffer) { + bus_dmamap_unload(sc->mge_rx_dtag, dw->buffer_dmap); + m_freem(dw->buffer); + } + } + + if (sc->mge_tx_dtag) { + mge_free_desc(sc, sc->mge_tx_desc, MGE_TX_DESC_NUM, + sc->mge_tx_dtag, 0); + bus_dma_tag_destroy(sc->mge_tx_dtag); + } + + if (sc->mge_rx_dtag) { + mge_free_desc(sc, sc->mge_rx_desc, MGE_RX_DESC_NUM, + sc->mge_rx_dtag, 0); + bus_dma_tag_destroy(sc->mge_rx_dtag); + } + + bus_dma_tag_destroy(sc->mge_desc_dtag); + + return (error); } static void @@ -552,8 +594,8 @@ mge_reinit_rx(struct mge_softc *sc) for (i = 0; i < MGE_RX_DESC_NUM; i++) { dw = &(sc->mge_rx_desc[i]); - mge_new_rxbuf(sc->mge_rx_dtag, dw->buffer_dmap, &dw->buffer, - &dw->mge_desc->buffer); + mge_new_rxbuf(sc->mge_rx_dtag, dw->buffer_dmap, + &dw->buffer, &dw->mge_desc->buffer); } sc->rx_desc_start = sc->mge_rx_desc[0].mge_desc_paddr; -- 1.6.3.1