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 <[email protected]>
@@ -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;
}