Date: Sun, 29 Aug 2010 21:05:35 +0000 (UTC) From: Nathan Whitehorn <nwhitehorn@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r211974 - user/nwhitehorn/ps3/powerpc/ps3 Message-ID: <201008292105.o7TL5ZgL074472@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: nwhitehorn Date: Sun Aug 29 21:05:34 2010 New Revision: 211974 URL: http://svn.freebsd.org/changeset/base/211974 Log: Fix a horrible memory leak in glc(4) where no TX buffers were ever freed. Performance is still bad (max 4.5 MB a second, so 40% wirespeed), but I can live with that. Modified: user/nwhitehorn/ps3/powerpc/ps3/if_glc.c Modified: user/nwhitehorn/ps3/powerpc/ps3/if_glc.c ============================================================================== --- user/nwhitehorn/ps3/powerpc/ps3/if_glc.c Sun Aug 29 20:53:24 2010 (r211973) +++ user/nwhitehorn/ps3/powerpc/ps3/if_glc.c Sun Aug 29 21:05:34 2010 (r211974) @@ -126,7 +126,8 @@ glc_attach(device_t dev) mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF); - sc->next_txdma_slot = sc->first_used_txdma_slot = 0; + sc->next_txdma_slot = 0; + sc->first_used_txdma_slot = -1; /* * Shut down existing tasks. @@ -333,14 +334,16 @@ static void glc_start_locked(struct ifnet *ifp) { struct glc_softc *sc = ifp->if_softc; - struct glc_txsoft *txs; bus_addr_t first, pktdesc; - int i, kickstart; + int kickstart = 0; struct mbuf *mb_head; mtx_assert(&sc->sc_mtx, MA_OWNED); first = 0; + if (STAILQ_EMPTY(&sc->sc_txdirtyq)) + kickstart = 1; + while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { IFQ_DRV_DEQUEUE(&ifp->if_snd, mb_head); @@ -366,23 +369,8 @@ glc_start_locked(struct ifnet *ifp) bus_dmamap_sync(sc->sc_dmadesc_tag, sc->sc_txdmadesc_map, BUS_DMASYNC_PREREAD); + /* XXX: kickstart always until problems are sorted out */ kickstart = 1; - STAILQ_FOREACH(txs, &sc->sc_txdirtyq, txs_q) { - for (i = txs->txs_firstdesc; - i != (txs->txs_lastdesc+1) % GLC_MAX_TX_PACKETS; - i = (i + 1) % GLC_MAX_TX_PACKETS) { - /* - * Check if any segments are currently being processed. - * If so, the DMA engine will pick up the bits we - * added eventually, otherwise restart DMA - */ - - if (sc->sc_txdmadesc[i].cmd_stat & GELIC_DESCR_OWNED) { - kickstart = 0; - break; - } - } - } if (kickstart && first != 0) { lv1_net_stop_tx_dma(sc->sc_bus, sc->sc_dev, 0); @@ -505,6 +493,10 @@ glc_encap(struct glc_softc *sc, struct m int nsegs = 16; int err = 0; + /* Check if the ring buffer is full */ + if (sc->next_txdma_slot == sc->first_used_txdma_slot) + return (-1); + /* Max number of segments is the number of free DMA slots */ if (sc->next_txdma_slot >= sc->first_used_txdma_slot) nsegs = 128 - sc->next_txdma_slot + sc->first_used_txdma_slot; @@ -578,16 +570,19 @@ glc_encap(struct glc_softc *sc, struct m idx = (idx + 1) % GLC_MAX_TX_PACKETS; } sc->next_txdma_slot = idx; - - bus_dmamap_sync(sc->sc_txdma_tag, txs->txs_dmamap, - BUS_DMASYNC_PREWRITE); - idx = (txs->txs_firstdesc - 1) % GLC_MAX_TX_PACKETS; sc->sc_txdmadesc[idx].next = firstslotphys; + if (sc->first_used_txdma_slot < 0) + sc->first_used_txdma_slot = txs->txs_firstdesc; + bus_dmamap_sync(sc->sc_txdma_tag, txs->txs_dmamap, BUS_DMASYNC_PREWRITE); + STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); + STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); + txs->txs_mbuf = *m_head; + if (pktdesc != NULL) *pktdesc = firstslotphys; @@ -653,7 +648,7 @@ glc_txintr(struct glc_softc *sc) while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { if (sc->sc_txdmadesc[txs->txs_lastdesc].cmd_stat - != GELIC_CMDSTAT_DMA_DONE) + & GELIC_DESCR_OWNED) break; STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); @@ -670,6 +665,11 @@ glc_txintr(struct glc_softc *sc) progress = 1; } + if (txs != NULL) + sc->first_used_txdma_slot = txs->txs_firstdesc; + else + sc->first_used_txdma_slot = -1; + if (progress) { /* * We freed some descriptors, so reset IFF_DRV_OACTIVE
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008292105.o7TL5ZgL074472>