Merge patch from PR 12605, which tidies up allocation of transmit DMA maps.

Generalize it to also tidy up allocation of receive DMA maps. And change a
few of the symbol names involved to (1) make sure all uses have been fixed
and (2) make it clearer what's actually going on.

Previously the driver was using DMA maps off the free list without fully
allocating them, apparently in order to save two or three lines releasing
them on error paths. According to the submitter of the PR (H.Saito) this
was causing it to reuse a map already in use when under load, resulting
in panics.

I'm not sure if that ought to have been possible or if it reflected an
interrupt handling bug somewhere else, but the change is an improvement
regardless, so we'll go with it.

Compile-tested only, but I've crosschecked the diffs and all that and it's
a pretty noninvasive change.

(Is anyone actually using this driver rather than tlp?)
This commit is contained in:
dholland 2009-03-29 05:26:43 +00:00
parent be5c9950c6
commit 3781289e95
2 changed files with 59 additions and 31 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_de.c,v 1.130 2009/03/18 16:00:19 cegger Exp $ */
/* $NetBSD: if_de.c,v 1.131 2009/03/29 05:26:43 dholland Exp $ */
/*-
* Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)
@ -37,7 +37,7 @@
* board which support 21040, 21041, or 21140 (mostly).
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_de.c,v 1.130 2009/03/18 16:00:19 cegger Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_de.c,v 1.131 2009/03/29 05:26:43 dholland Exp $");
#define TULIP_HDR_DATA
@ -200,6 +200,32 @@ static int tulip_ifmedia_change(struct ifnet * const ifp);
static void tulip_ifmedia_status(struct ifnet * const ifp, struct ifmediareq *req);
#endif
/* static void tulip_21140_map_media(tulip_softc_t *sc); */
static bus_dmamap_t
tulip_alloc_rxmap(tulip_softc_t *sc)
{
return (sc->tulip_free_rxmaps[--sc->tulip_num_free_rxmaps]);
}
static void
tulip_free_rxmap(tulip_softc_t *sc, bus_dmamap_t map)
{
sc->tulip_free_rxmaps[sc->tulip_num_free_rxmaps++] = map;
}
static bus_dmamap_t
tulip_alloc_txmap(tulip_softc_t *sc)
{
return (sc->tulip_free_txmaps[--sc->tulip_num_free_txmaps]);
}
static void
tulip_free_txmap(tulip_softc_t *sc, bus_dmamap_t map)
{
sc->tulip_free_txmaps[sc->tulip_num_free_txmaps++] = map;
}
static void
tulip_timeout_callback(
@ -3374,7 +3400,7 @@ tulip_reset(
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX)
map = M_GETCTX(m, bus_dmamap_t);
bus_dmamap_unload(sc->tulip_dmatag, map);
sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
tulip_free_txmap(sc, map);
#endif
m_freem(m);
}
@ -3420,7 +3446,7 @@ tulip_reset(
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX)
map = M_GETCTX(m, bus_dmamap_t);
bus_dmamap_unload(sc->tulip_dmatag, map);
sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
tulip_free_rxmap(sc, map);
#endif
m_freem(m);
}
@ -3587,7 +3613,7 @@ tulip_rx_intr(
map = M_GETCTX(me, bus_dmamap_t);
TULIP_RXMAP_POSTSYNC(sc, map);
bus_dmamap_unload(sc->tulip_dmatag, map);
sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
tulip_free_rxmap(sc, map);
#if defined(DIAGNOSTIC)
M_SETCTX(me, NULL);
#endif
@ -3619,7 +3645,7 @@ tulip_rx_intr(
bus_dmamap_sync(sc->tulip_dmatag, map, 0, me->m_len,
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->tulip_dmatag, map);
sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
tulip_free_rxmap(sc, map);
#if defined(DIAGNOSTIC)
M_SETCTX(me, NULL);
#endif
@ -3681,7 +3707,7 @@ tulip_rx_intr(
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX)
map = M_GETCTX(me, bus_dmamap_t);
bus_dmamap_unload(sc->tulip_dmatag, map);
sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
tulip_free_rxmap(sc, map);
#if defined(DIAGNOSTIC)
M_SETCTX(me, NULL);
#endif
@ -3781,8 +3807,8 @@ tulip_rx_intr(
do {
tulip_desc_t * const nextout = ri->ri_nextout;
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX)
if (sc->tulip_rxmaps_free > 0) {
map = sc->tulip_rxmaps[--sc->tulip_rxmaps_free];
if (sc->tulip_num_free_rxmaps > 0) {
map = tulip_alloc_rxmap(sc);
} else {
m_freem(ms);
sc->tulip_flags |= TULIP_RXBUFSLOW;
@ -3882,7 +3908,7 @@ tulip_tx_intr(
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX)
bus_dmamap_t map = M_GETCTX(m, bus_dmamap_t);
TULIP_TXMAP_POSTSYNC(sc, map);
sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
tulip_free_txmap(sc, map);
#endif /* TULIP_BUS_DMA */
#if NBPFILTER > 0
if (sc->tulip_bpf != NULL)
@ -4381,14 +4407,14 @@ tulip_txput(
/*
* Reclaim some DMA maps from if we are out.
*/
if (sc->tulip_txmaps_free == 0) {
if (sc->tulip_num_free_txmaps == 0) {
#if defined(TULIP_DEBUG)
sc->tulip_dbg.dbg_no_txmaps++;
#endif
freedescs += tulip_tx_intr(sc);
}
if (sc->tulip_txmaps_free > 0) {
map = sc->tulip_txmaps[sc->tulip_txmaps_free-1];
if (sc->tulip_num_free_txmaps > 0) {
map = tulip_alloc_txmap(sc);
} else {
sc->tulip_flags |= TULIP_WANTTXSTART;
#if defined(TULIP_DEBUG)
@ -4409,6 +4435,7 @@ tulip_txput(
#if defined(TULIP_DEBUG)
sc->tulip_dbg.dbg_txput_finishes[2]++;
#endif
tulip_free_txmap(sc, map);
goto finish;
}
error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT);
@ -4419,6 +4446,7 @@ tulip_txput(
#if defined(TULIP_DEBUG)
sc->tulip_dbg.dbg_txput_finishes[3]++;
#endif
tulip_free_txmap(sc, map);
goto finish;
}
}
@ -4438,6 +4466,7 @@ tulip_txput(
sc->tulip_dbg.dbg_txput_finishes[4]++;
#endif
bus_dmamap_unload(sc->tulip_dmatag, map);
tulip_free_txmap(sc, map);
goto finish;
}
for (; map->dm_nsegs - segcnt > 1; segcnt += 2) {
@ -4466,7 +4495,6 @@ tulip_txput(
TULIP_TXMAP_PRESYNC(sc, map);
M_SETCTX(m, map);
map = NULL;
--sc->tulip_txmaps_free; /* commit to using the dmamap */
#else /* !TULIP_BUS_DMA */
@ -5208,18 +5236,18 @@ tulip_busdma_init(
}
/*
* Allocate dmamaps for each transmit descriptors
* Allocate dmamaps for each transmit descriptor, and place on the
* free list.
*/
if (error == 0) {
while (error == 0 && sc->tulip_txmaps_free < TULIP_TXDESCS) {
while (error == 0 && sc->tulip_num_free_txmaps < TULIP_TXDESCS) {
bus_dmamap_t map;
if ((error = TULIP_TXMAP_CREATE(sc, &map)) == 0)
sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
tulip_free_txmap(sc, map);
}
if (error) {
while (sc->tulip_txmaps_free > 0)
bus_dmamap_destroy(sc->tulip_dmatag,
sc->tulip_txmaps[--sc->tulip_txmaps_free]);
while (sc->tulip_num_free_txmaps > 0)
bus_dmamap_destroy(sc->tulip_dmatag, tulip_alloc_txmap(sc));
}
}
#else
@ -5240,18 +5268,18 @@ tulip_busdma_init(
}
/*
* Allocate dmamaps for each receive descriptors
* Allocate dmamaps for each receive descriptor, and place on the
* free list.
*/
if (error == 0) {
while (error == 0 && sc->tulip_rxmaps_free < TULIP_RXDESCS) {
while (error == 0 && sc->tulip_num_free_rxmaps < TULIP_RXDESCS) {
bus_dmamap_t map;
if ((error = TULIP_RXMAP_CREATE(sc, &map)) == 0)
sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
tulip_free_rxmap(sc, map);
}
if (error) {
while (sc->tulip_rxmaps_free > 0)
bus_dmamap_destroy(sc->tulip_dmatag,
sc->tulip_rxmaps[--sc->tulip_rxmaps_free]);
while (sc->tulip_num_free_rxmaps > 0)
bus_dmamap_destroy(sc->tulip_dmatag, tulip_alloc_rxmap(sc));
}
}
#else

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_devar.h,v 1.50 2008/06/12 22:44:47 cegger Exp $ */
/* $NetBSD: if_devar.h,v 1.51 2009/03/29 05:26:43 dholland Exp $ */
/*-
* Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)
@ -509,13 +509,13 @@ struct _tulip_softc_t {
#if !defined(TULIP_BUS_DMA_NOTX)
bus_dmamap_t tulip_setupmap;
bus_dmamap_t tulip_txdescmap;
bus_dmamap_t tulip_txmaps[TULIP_TXDESCS];
unsigned tulip_txmaps_free;
bus_dmamap_t tulip_free_txmaps[TULIP_TXDESCS];
unsigned tulip_num_free_txmaps;
#endif
#if !defined(TULIP_BUS_DMA_NORX)
bus_dmamap_t tulip_rxdescmap;
bus_dmamap_t tulip_rxmaps[TULIP_RXDESCS];
unsigned tulip_rxmaps_free;
bus_dmamap_t tulip_free_rxmaps[TULIP_RXDESCS];
unsigned tulip_num_free_rxmaps;
#endif
#endif
#if !defined(__NetBSD__)