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.
This commit is contained in:
phk 2001-03-13 09:29:37 +00:00
parent e8dd3f93fc
commit d8ffdbd577

View File

@ -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;
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;
}
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;
}
if (++sch->tx_next_md >= sch->nmd)
sch->tx_next_md = 0;
md->data = vtophys(m->m_data);
len -= m->m_len;
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;
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;
}
m = m->m_next;
md->data = vtophys(m->m_data);
if (md == md0)
u = 0x00000000; /* OWNER = CPU */
else
u = 0x80000000; /* OWNER = MUSYCC */
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;
}
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]);