Subject: kern/12605: panic: _bus_dmamap_sync
To: None <gnats-bugs@gnats.netbsd.org>
From: H.Saito <saito@densan.co.jp>
List: netbsd-bugs
Date: 04/09/2001 21:27:24
>Number:         12605
>Category:       kern
>Synopsis:       bug of sys/dev/pci/if_de.c
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Apr 10 17:58:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     H.Saito
>Release:        1.5
>Organization:
>Environment:
    DCP-R5000/30(DENSAN Compact-PCI bus Board)
    big-endian, mips1, ELF
System: NetBSD vw5 1.5 NetBSD 1.5 (GENERIC) #4: Mon Apr 9 16:40:41 JST 2001 saito@vw4:/user5/NetBSD-1.5/usr/src/sys/arch/devos/compile/GENERIC devos


>Description:
    A duplicate dma maps pointer was allocated from tulip_txput()
    of sys/dev/pci/if_de.c.

    Mayby, this Program is wrong, please see below.

    if (sc->tulip_txmaps_free > 0) {
        map = sc->tulip_txmaps[sc->tulip_txmaps_free-1];
    } else {
        ...
    }
    ...
    --sc->tulip_txmaps_free;            /* commit to using the dmamap */

>How-To-Repeat:
    If NetBSD-1.5 transfer too many data with another machine by TCP/IP,
    and cp a large file to /mnt that mounted by nfs with another machine,
    immediately crashed(panic: _bus_dmamap_sync).

>Fix:
--- if_de.c.org	Thu Mar 23 16:01:37 2000
+++ if_de.c	Mon Apr  9 15:14:38 2001
@@ -3296,6 +3303,30 @@
 #endif
 }
 
+
+static void put_tulip_txmaps(tulip_softc_t * const sc, bus_dmamap_t map);
+static bus_dmamap_t get_tulip_txmaps(tulip_softc_t * const sc);
+
+static void
+put_tulip_txmaps(tulip_softc_t * const sc, bus_dmamap_t map)
+{
+#if defined(TULIP_TXMAPS_DEBUG)
+	int n;
+
+	for (n = 0; n < sc->tulip_txmaps_free; n++) {
+		if (sc->tulip_txmaps[n] == map)
+			printf("put_tulip_txmaps: %d: 0x%x\n", n, (int)map);
+	}
+#endif
+	sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
+}
+
+static bus_dmamap_t
+get_tulip_txmaps(tulip_softc_t * const sc)
+{
+	return (sc->tulip_txmaps[--sc->tulip_txmaps_free]);
+}
+
 static void
 tulip_reset(
     tulip_softc_t * const sc)
@@ -3360,7 +3396,7 @@
 #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;
+	put_tulip_txmaps(sc, map);
 #endif
 	m_freem(m);
     }
@@ -3868,7 +3904,7 @@
 #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;
+		    put_tulip_txmaps(sc, map);
 #endif /* TULIP_BUS_DMA */
 #if NBPFILTER > 0
 		    if (sc->tulip_bpf != NULL)
@@ -4374,7 +4410,7 @@
 	free += tulip_tx_intr(sc);
     }
     if (sc->tulip_txmaps_free > 0) {
-	map = sc->tulip_txmaps[sc->tulip_txmaps_free-1];
+	map = get_tulip_txmaps(sc);
     } else {
 	sc->tulip_flags |= TULIP_WANTTXSTART;
 #if defined(TULIP_DEBUG)
@@ -4395,6 +4431,7 @@
 #if defined(TULIP_DEBUG)
 		sc->tulip_dbg.dbg_txput_finishes[2]++;
 #endif
+		put_tulip_txmaps(sc, map);
 		goto finish;
 	    }
 	    error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT);
@@ -4405,6 +4442,7 @@
 #if defined(TULIP_DEBUG)
 	    sc->tulip_dbg.dbg_txput_finishes[3]++;
 #endif
+	    put_tulip_txmaps(sc, map);
 	    goto finish;
 	}
     }
@@ -4424,6 +4462,7 @@
 	sc->tulip_dbg.dbg_txput_finishes[4]++;
 #endif
 	bus_dmamap_unload(sc->tulip_dmatag, map);
+	put_tulip_txmaps(sc, map);
 	goto finish;
     }
     for (; map->dm_nsegs - segcnt > 1; segcnt += 2) {
@@ -4452,7 +4491,6 @@
     TULIP_TXMAP_PRESYNC(sc, map);
     M_SETCTX(m, map);
     map = NULL;
-    --sc->tulip_txmaps_free;		/* commit to using the dmamap */
 
 #else /* !TULIP_BUS_DMA */
 
@@ -5237,12 +5275,11 @@
 	while (error == 0 && sc->tulip_txmaps_free < TULIP_TXDESCS) {
 	    bus_dmamap_t map;
 	    if ((error = TULIP_TXMAP_CREATE(sc, &map)) == 0)
-		sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
+		put_tulip_txmaps(sc, map);
 	}
 	if (error) {
 	    while (sc->tulip_txmaps_free > 0) 
-		bus_dmamap_destroy(sc->tulip_dmatag,
-				   sc->tulip_txmaps[--sc->tulip_txmaps_free]);
+		bus_dmamap_destroy(sc->tulip_dmatag, get_tulip_txmaps(sc));
 	}
     }
 #else
>Release-Note:
>Audit-Trail:
>Unformatted: