Module Name: src Committed By: mlelstv Date: Sun Aug 25 08:31:07 UTC 2024
Modified Files: src/sys/dev/ic: bcmgenet.c Log Message: Fix mbuf leak. Minor optimizations for send queue. To generate a diff of this commit: cvs rdiff -u -r1.17 -r1.18 src/sys/dev/ic/bcmgenet.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ic/bcmgenet.c diff -u src/sys/dev/ic/bcmgenet.c:1.17 src/sys/dev/ic/bcmgenet.c:1.18 --- src/sys/dev/ic/bcmgenet.c:1.17 Sun Aug 25 08:27:06 2024 +++ src/sys/dev/ic/bcmgenet.c Sun Aug 25 08:31:07 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: bcmgenet.c,v 1.17 2024/08/25 08:27:06 mlelstv Exp $ */ +/* $NetBSD: bcmgenet.c,v 1.18 2024/08/25 08:31:07 mlelstv Exp $ */ /*- * Copyright (c) 2020 Jared McNeill <jmcne...@invisible.ca> @@ -34,7 +34,7 @@ #include "opt_ddb.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: bcmgenet.c,v 1.17 2024/08/25 08:27:06 mlelstv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bcmgenet.c,v 1.18 2024/08/25 08:31:07 mlelstv Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -621,11 +621,33 @@ genet_init(struct ifnet *ifp) return error; } +static int +genet_free_txbuf(struct genet_softc *sc, int index) +{ + struct genet_bufmap *bmap; + + bmap = &sc->sc_tx.buf_map[index]; + if (bmap->mbuf == NULL) + return 0; + + if (bmap->map->dm_mapsize > 0) { + bus_dmamap_sync(sc->sc_tx.buf_tag, bmap->map, + 0, bmap->map->dm_mapsize, + BUS_DMASYNC_POSTWRITE); + } + bus_dmamap_unload(sc->sc_tx.buf_tag, bmap->map); + m_freem(bmap->mbuf); + bmap->mbuf = NULL; + + return 1; +} + static void genet_stop_locked(struct genet_softc *sc, int disable) { struct ifnet *ifp = &sc->sc_ec.ec_if; uint32_t val; + int i; GENET_ASSERT_LOCKED(sc); @@ -661,6 +683,10 @@ genet_stop_locked(struct genet_softc *sc /* Disable interrupts */ genet_disable_intr(sc); + /* Free TX buffers */ + for (i=0; i<=TX_DESC_COUNT; ++i) + genet_free_txbuf(sc, i); + ifp->if_flags &= ~IFF_RUNNING; } @@ -771,34 +797,22 @@ static void genet_txintr(struct genet_softc *sc, int qid) { struct ifnet *ifp = &sc->sc_ec.ec_if; - struct genet_bufmap *bmap; int cidx, i, pkts = 0; cidx = RD4(sc, GENET_TX_DMA_CONS_INDEX(qid)) & 0xffff; i = sc->sc_tx.cidx % TX_DESC_COUNT; while (sc->sc_tx.cidx != cidx) { - bmap = &sc->sc_tx.buf_map[i]; - if (bmap->mbuf != NULL) { - /* XXX first segment already unloads */ - if (bmap->map->dm_mapsize > 0) { - bus_dmamap_sync(sc->sc_tx.buf_tag, bmap->map, - 0, bmap->map->dm_mapsize, - BUS_DMASYNC_POSTWRITE); - } - bus_dmamap_unload(sc->sc_tx.buf_tag, bmap->map); - m_freem(bmap->mbuf); - bmap->mbuf = NULL; - ++pkts; - } - + pkts += genet_free_txbuf(sc, i); i = TX_NEXT(i); sc->sc_tx.cidx = (sc->sc_tx.cidx + 1) & 0xffff; } - if_statadd(ifp, if_opackets, pkts); - - if (pkts != 0) + if (pkts != 0) { + if_statadd(ifp, if_opackets, pkts); rnd_add_uint32(&sc->sc_rndsource, pkts); + } + + if_schedule_deferred_start(ifp); } static void @@ -819,7 +833,11 @@ genet_start_locked(struct genet_softc *s cnt = 0; sc->sc_tx.queued = (RD4(sc, GENET_TX_DMA_PROD_INDEX(qid)) - - RD4(sc, GENET_TX_DMA_CONS_INDEX(qid))) & 0xffff; + - sc->sc_tx.cidx) & 0xffff; + + /* At least one descriptor free ? */ + if (sc->sc_tx.queued >= TX_DESC_COUNT - 1) + return; for (;;) { IFQ_POLL(&ifp->if_snd, m); @@ -863,9 +881,7 @@ int genet_intr(void *arg) { struct genet_softc *sc = arg; - struct ifnet *ifp = &sc->sc_ec.ec_if; uint32_t val; - bool dotx = false; val = RD4(sc, GENET_INTRL2_CPU_STAT); val &= ~RD4(sc, GENET_INTRL2_CPU_STAT_MASK); @@ -879,12 +895,8 @@ genet_intr(void *arg) if (val & GENET_IRQ_TXDMA_DONE) { genet_txintr(sc, GENET_DMA_DEFAULT_QUEUE); - dotx = true; } - if (dotx) - if_schedule_deferred_start(ifp); - return 1; }