This commit fixes two bugs in the de driver. The first is that the

descriptor count gets miscounted on txprobes.  The second (and more
important) is that transmit stalls should now be fixed.  The problem
was not due to lack of ring resources but dmamaps.  When Jason changed
the driver to use pre-allocated maps (instead of the dynamic ones I
used), and when there were no more maps, the driver just gave up instead
of calling tx_intr to free any transmitted but unreclaimed dma maps.
Since there was nothing being transmitted, no transmit interrupts
would fire to restore things (and OACTIVE prevented other transmits
from happenning).  So it stayed starved until another interrupt cause
(like a received packet) "woke" it up.
This commit is contained in:
matt 1998-09-15 02:39:03 +00:00
parent 765a4daca2
commit 2633c65da5
2 changed files with 48 additions and 24 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_de.c,v 1.76 1998/08/28 20:58:37 drochner Exp $ */ /* $NetBSD: if_de.c,v 1.77 1998/09/15 02:39:03 matt Exp $ */
/*- /*-
* Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com) * Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)
@ -3694,6 +3694,8 @@ tulip_tx_intr(
if (((volatile tulip_desc_t *) ri->ri_nextin)->d_status & TULIP_DSTS_OWNER) if (((volatile tulip_desc_t *) ri->ri_nextin)->d_status & TULIP_DSTS_OWNER)
break; break;
ri->ri_free++;
descs++;
d_flag = ri->ri_nextin->d_flag; d_flag = ri->ri_nextin->d_flag;
if (d_flag & TULIP_DFLAG_TxLASTSEG) { if (d_flag & TULIP_DFLAG_TxLASTSEG) {
if (d_flag & TULIP_DFLAG_TxSETUPPKT) { if (d_flag & TULIP_DFLAG_TxSETUPPKT) {
@ -3794,8 +3796,6 @@ tulip_tx_intr(
if (++ri->ri_nextin == ri->ri_last) if (++ri->ri_nextin == ri->ri_last)
ri->ri_nextin = ri->ri_first; ri->ri_nextin = ri->ri_first;
ri->ri_free++;
descs++;
if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0) if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0)
sc->tulip_if.if_flags &= ~IFF_OACTIVE; sc->tulip_if.if_flags &= ~IFF_OACTIVE;
} }
@ -4189,6 +4189,7 @@ tulip_txput(
TULIP_PRINTF_ARGS, TULIP_PRINTF_ARGS,
(sc->tulip_flags & TULIP_TXPROBE_ACTIVE) ? "(probe)" : ""); (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) ? "(probe)" : "");
sc->tulip_flags |= TULIP_WANTTXSTART; sc->tulip_flags |= TULIP_WANTTXSTART;
sc->tulip_dbg.dbg_txput_finishes[0]++;
goto finish; goto finish;
} }
#endif #endif
@ -4220,36 +4221,45 @@ tulip_txput(
free = ri->ri_free; free = ri->ri_free;
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX) #if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX)
/*
* Reclaim some dma maps from if we are out.
*/
if (sc->tulip_txmaps_free == 0)
free += tulip_tx_intr(sc);
if (sc->tulip_txmaps_free > 0) { if (sc->tulip_txmaps_free > 0) {
map = sc->tulip_txmaps[--sc->tulip_txmaps_free]; map = sc->tulip_txmaps[--sc->tulip_txmaps_free];
} else { } else {
sc->tulip_flags |= TULIP_WANTTXSTART; sc->tulip_flags |= TULIP_WANTTXSTART;
#if defined(TULIP_DEBUG)
sc->tulip_dbg.dbg_txput_finishes[1]++;
#endif
goto finish; goto finish;
} }
error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT); error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT);
if (error == EFBIG) { if (error != 0) {
/* if (error == EFBIG) {
* The packet exceeds the number of transmit buffer /*
* entries that we can use for one packet, so we have * The packet exceeds the number of transmit buffer
* to recopy it into one mbuf and then try again. * entries that we can use for one packet, so we have
*/ * to recopy it into one mbuf and then try again.
m = tulip_mbuf_compress(m); */
if (m == NULL) m = tulip_mbuf_compress(m);
goto finish; if (m == NULL) {
error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT); #if defined(TULIP_DEBUG)
if (error) { sc->tulip_dbg.dbg_txput_finishes[2]++;
#endif
goto finish;
}
error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT);
}
if (error != 0) {
printf(TULIP_PRINTF_FMT ": unable to load tx map, " printf(TULIP_PRINTF_FMT ": unable to load tx map, "
"error = %d\n", TULIP_PRINTF_ARGS, error); "error = %d\n", TULIP_PRINTF_ARGS, error);
#if defined(TULIP_DEBUG)
sc->tulip_dbg.dbg_txput_finishes[3]++;
#endif
goto finish; goto finish;
} }
} else if (error != 0) {
/*
* Some other error (possibly resource shortage?) has ocurred.
* Report it.
*/
printf(TULIP_PRINTF_FMT ": unable to load tx map, error = %d\n",
TULIP_PRINTF_ARGS, error);
goto finish;
} }
if ((free -= (map->dm_nsegs + 1) / 2) <= 0 if ((free -= (map->dm_nsegs + 1) / 2) <= 0
/* /*
@ -4263,6 +4273,9 @@ tulip_txput(
* mbuf and return. * mbuf and return.
*/ */
sc->tulip_flags |= TULIP_WANTTXSTART; sc->tulip_flags |= TULIP_WANTTXSTART;
#if defined(TULIP_DEBUG)
sc->tulip_dbg.dbg_txput_finishes[4]++;
#endif
goto finish; goto finish;
} }
for (; map->dm_nsegs - segcnt > 1; segcnt += 2) { for (; map->dm_nsegs - segcnt > 1; segcnt += 2) {
@ -4332,6 +4345,9 @@ tulip_txput(
* mbuf and return. * mbuf and return.
*/ */
sc->tulip_flags |= TULIP_WANTTXSTART; sc->tulip_flags |= TULIP_WANTTXSTART;
#if defined(TULIP_DEBUG)
sc->tulip_dbg.dbg_txput_finishes[1]++;
#endif
goto finish; goto finish;
} }
} }
@ -4434,9 +4450,11 @@ tulip_txput(
* switch back to the single queueing ifstart. * switch back to the single queueing ifstart.
*/ */
sc->tulip_flags &= ~TULIP_WANTTXSTART; sc->tulip_flags &= ~TULIP_WANTTXSTART;
sc->tulip_if.if_start = tulip_ifstart_one;
if (sc->tulip_txtimer == 0) if (sc->tulip_txtimer == 0)
sc->tulip_txtimer = TULIP_TXTIMER; sc->tulip_txtimer = TULIP_TXTIMER;
#if defined(TULIP_DEBUG)
sc->tulip_dbg.dbg_txput_finishes[5]++;
#endif
/* /*
* If we want a txstart, there must be not enough space in the * If we want a txstart, there must be not enough space in the
@ -4448,6 +4466,9 @@ tulip_txput(
* WANTTXSTART thereby causing TXINTR to be cleared. * WANTTXSTART thereby causing TXINTR to be cleared.
*/ */
finish: finish:
#if defined(TULIP_DEBUG)
sc->tulip_dbg.dbg_txput_finishes[6]++;
#endif
if (sc->tulip_flags & (TULIP_WANTTXSTART|TULIP_DOINGSETUP)) { if (sc->tulip_flags & (TULIP_WANTTXSTART|TULIP_DOINGSETUP)) {
sc->tulip_if.if_flags |= IFF_OACTIVE; sc->tulip_if.if_flags |= IFF_OACTIVE;
sc->tulip_if.if_start = tulip_ifstart; sc->tulip_if.if_start = tulip_ifstart;
@ -4758,6 +4779,8 @@ tulip_ifstart(
break; break;
} }
} }
if (sc->tulip_if.if_snd.ifq_head == NULL)
sc->tulip_if.if_start = tulip_ifstart_one;
} }
TULIP_PERFEND(ifstart); TULIP_PERFEND(ifstart);

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_devar.h,v 1.28 1998/08/13 02:10:53 eeh Exp $ */ /* $NetBSD: if_devar.h,v 1.29 1998/09/15 02:39:03 matt Exp $ */
/*- /*-
* Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com) * Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)
@ -630,6 +630,7 @@ struct _tulip_softc_t {
u_int32_t dbg_rxintrs; u_int32_t dbg_rxintrs;
u_int32_t dbg_last_rxintrs; u_int32_t dbg_last_rxintrs;
u_int32_t dbg_high_rxintrs_hz; u_int32_t dbg_high_rxintrs_hz;
u_int32_t dbg_txput_finishes[8];
u_int32_t dbg_txprobes_ok[TULIP_MEDIA_MAX]; u_int32_t dbg_txprobes_ok[TULIP_MEDIA_MAX];
u_int32_t dbg_txprobes_failed[TULIP_MEDIA_MAX]; u_int32_t dbg_txprobes_failed[TULIP_MEDIA_MAX];
u_int32_t dbg_events[TULIP_MEDIAPOLL_MAX]; u_int32_t dbg_events[TULIP_MEDIAPOLL_MAX];