From 07103528896aa38497e94cad2f4161aeb1471368 Mon Sep 17 00:00:00 2001 From: phk Date: Tue, 13 Mar 2001 09:29:37 +0000 Subject: Fix a race condition in the transmit path caused by the controller caching a bit more than we were told initially. More statistics gathering as well. --- sys/dev/musycc/musycc.c | 148 ++++++++++++++++++++++++++++++------------------ 1 file changed, 94 insertions(+), 54 deletions(-) (limited to 'sys/dev/musycc') diff --git a/sys/dev/musycc/musycc.c b/sys/dev/musycc/musycc.c index d9d4b37..4551c14 100644 --- a/sys/dev/musycc/musycc.c +++ b/sys/dev/musycc/musycc.c @@ -148,6 +148,7 @@ struct mdesc { u_int32_t next; /* Software only */ struct mbuf *m; + struct mdesc *snext; }; #define NPORT 8 @@ -170,8 +171,8 @@ struct schan { u_long rx_drop; /* mbuf allocation failures */ u_long tx_limit; u_long tx_pending; - int tx_next_md; /* index to the next MD */ - int tx_last_md; /* index to the last MD */ + struct mdesc *tx_next_md; /* next MD */ + struct mdesc *tx_last_md; /* last MD */ int rx_last_md; /* index to next MD */ int nmd; /* count of MD's. */ @@ -183,9 +184,14 @@ struct schan { u_long long_error; u_long abort_error; u_long short_error; + u_long txn, rxn; time_t last_xmit; time_t last_txerr; + + time_t last_txdrop; + u_long tx_drop; + #if 0 @@ -399,7 +405,7 @@ init_ctrl(struct softc *sc) sc->ram->grcd |= 0x00000020; /* MSKCOFA */ - sc->ram->grcd |= 0x00000400; /* POLLTH=1 */ + sc->ram->grcd |= 0x00000440; /* POLLTH=1 */ sc->ram->mpd = 0; /* Memory Protection NI [5-18] */ @@ -441,15 +447,21 @@ status_chans(struct softc *sc, char *s) sprintf(s + strlen(s), " ts %08x", scp->ts); sprintf(s + strlen(s), " RX %lus/%lus", time_second - scp->last_recv, time_second - scp->last_rxerr); - sprintf(s + strlen(s), " TX %lus/%lus", - time_second - scp->last_xmit, time_second - scp->last_txerr); + sprintf(s + strlen(s), " TX %lus/%lus/%lus", + time_second - scp->last_xmit, + time_second - scp->last_txerr, + time_second - scp->last_txdrop); + sprintf(s + strlen(s), " TXdrop %lu Pend %lu", + scp->tx_drop, + scp->tx_pending); sprintf(s + strlen(s), " CRC %lu Dribble %lu Long %lu Short %lu Abort %lu", scp->crc_error, scp->dribble_error, scp->long_error, scp->short_error, scp->abort_error); - sprintf(s + strlen(s), "\n"); + sprintf(s + strlen(s), "\n TX: %lu RX: %lu\n", + scp->txn, scp->rxn); } } @@ -623,9 +635,7 @@ init_8370(struct softc *sc) static void musycc_intr0_tx_eom(struct softc *sc, int ch) { - u_int32_t status; struct schan *sch; - struct mbuf *m; struct mdesc *md; sch = sc->chan[ch]; @@ -636,22 +646,19 @@ musycc_intr0_tx_eom(struct softc *sc, int ch) if (sc->mdt[ch] == NULL) return; /* XXX: can this happen ? */ for (;;) { - if (sch->tx_last_md == sch->tx_next_md) + md = sch->tx_last_md; + if (md->status == 0) break; - md = &sc->mdt[ch][sch->tx_last_md]; - status = md->status; - if (status & 0x80000000) + if (md->status & 0x80000000) break; /* Not our mdesc, done */ + sch->tx_last_md = md->snext; md->data = 0; - m = md->m; - if (m != NULL) { - sch->tx_pending -= m->m_pkthdr.len; - m_freem(m); + if (md->m != NULL) { + sch->tx_pending -= md->m->m_pkthdr.len; + m_freem(md->m); md->m = NULL; } md->status = 0; - if (++sch->tx_last_md >= sch->nmd) - sch->tx_last_md = 0; } } @@ -1085,8 +1092,8 @@ musycc_rcvdata(hook_p hook, item_p item) struct softc *sc; struct csoftc *csc; struct schan *sch; - struct mdesc *md; - u_int32_t ch, u, len; + struct mdesc *md, *md0; + u_int32_t ch, u, u0, len; struct mbuf *m2; struct mbuf *m; @@ -1110,43 +1117,73 @@ musycc_rcvdata(hook_p hook, item_p item) NGI_GET_M(item, m); NG_FREE_ITEM(item); if (sch->tx_pending + m->m_pkthdr.len > sch->tx_limit * maxlatency) { - printf("pend %ld len %d lim %ld\n", sch->tx_pending, - m->m_pkthdr.len, sch->tx_limit * maxlatency); + sch->tx_drop++; + sch->last_txdrop = time_second; NG_FREE_M(m); return (0); } - + /* find out if we have enough txmd's */ m2 = m; - len = m->m_pkthdr.len; - while (len) { - if (m->m_len > 0) { /* XXX: needed ? */ - md = &sc->mdt[ch][sch->tx_next_md]; - if ((md->status & 0x80000000) != 0x00000000) { - printf("Out of tx md\n"); - sch->last_txerr = time_second; - break; - } + md = sch->tx_next_md; + for (len = m2->m_pkthdr.len; len; m2 = m2->m_next) { + if (m2->m_len == 0) + continue; + if (md->status != 0) { + sch->tx_drop++; + sch->last_txdrop = time_second; + NG_FREE_M(m); + return (0); + } + len -= m2->m_len; + md = md->snext; + } - if (++sch->tx_next_md >= sch->nmd) - sch->tx_next_md = 0; + m2 = m; + md = md0 = sch->tx_next_md; + u0 = 0; + for (len = m->m_pkthdr.len; len > 0; m = m->m_next) { + if (m->m_len == 0) + continue; + if (md->status != 0) { + printf("Out of tx md(2)\n"); + sch->last_txerr = time_second; + sch->tx_drop++; + sch->last_txdrop = time_second; + NG_FREE_M(m); + break; + } - md->data = vtophys(m->m_data); - len -= m->m_len; + md->data = vtophys(m->m_data); + if (md == md0) + u = 0x00000000; /* OWNER = CPU */ + else u = 0x80000000; /* OWNER = MUSYCC */ - if (len > 0) { - md->m = 0; - } else { - u |= 1 << 29; /* EOM */ - md->m = m2; - sch->tx_pending += m2->m_pkthdr.len; - } - u |= m->m_len; - md->status = u; - sch->last_xmit = time_second; + u |= m->m_len; + len -= m->m_len; + if (len > 0) { + md->m = NULL; + if (md == md0) + u0 = u; + else + md->status = u; + md = md->snext; + continue; } - m = m->m_next; + u |= 0x20000000; /* EOM */ + md->m = m2; + sch->tx_pending += m2->m_pkthdr.len; + if (md == md0) { + u |= 0x80000000; /* OWNER = MUSYCC */ + md->status = u; + } else { + md->status = u; + md0->status = u0 | 0x80000000; /* OWNER = MUSYCC */ + } + sch->last_xmit = time_second; + sch->tx_next_md = md->snext; } + sch->txn++; return (0); } @@ -1226,21 +1263,23 @@ musycc_connect(hook_p hook) * 1 timeslot, 50 bytes packets -> 68msec * 31 timeslots, 50 bytes packets -> 14msec */ - sch->nmd = nmd = 40 + nts * 4; + sch->nmd = nmd = 200 + nts * 4; sch->rx_last_md = 0; - sch->tx_next_md = 0; - sch->tx_last_md = 0; MALLOC(sc->mdt[ch], struct mdesc *, sizeof(struct mdesc) * nmd, M_MUSYCC, M_WAITOK); MALLOC(sc->mdr[ch], struct mdesc *, sizeof(struct mdesc) * nmd, M_MUSYCC, M_WAITOK); for (i = 0; i < nmd; i++) { if (i == nmd - 1) { - sc->mdt[ch][i].next = vtophys(&sc->mdt[ch][0]); - sc->mdr[ch][i].next = vtophys(&sc->mdr[ch][0]); + sc->mdt[ch][i].snext = &sc->mdt[ch][0]; + sc->mdt[ch][i].next = vtophys(sc->mdt[ch][i].snext); + sc->mdr[ch][i].snext = &sc->mdr[ch][0]; + sc->mdr[ch][i].next = vtophys(sc->mdr[ch][i].snext); } else { - sc->mdt[ch][i].next = vtophys(&sc->mdt[ch][i + 1]); - sc->mdr[ch][i].next = vtophys(&sc->mdr[ch][i + 1]); + sc->mdt[ch][i].snext = &sc->mdt[ch][i + 1]; + sc->mdt[ch][i].next = vtophys(sc->mdt[ch][i].snext); + sc->mdr[ch][i].snext = &sc->mdr[ch][i + 1]; + sc->mdr[ch][i].next = vtophys(sc->mdr[ch][i].snext); } sc->mdt[ch][i].status = 0; sc->mdt[ch][i].m = NULL; @@ -1262,6 +1301,7 @@ musycc_connect(hook_p hook) sc->mdr[ch][i].data = vtophys(m->m_data); sc->mdr[ch][i].status = 1600; /* MTU */ } + sch->tx_last_md = sch->tx_next_md = &sc->mdt[ch][0]; /* Configure it into the chip */ sc->ram->thp[ch] = vtophys(&sc->mdt[ch][0]); -- cgit v1.1