Fix a race condition that was introduced since pccbb interrupts are

flag'ed INTR_MPSAFE.  In ep_if_start(), use the IF_DEQUEUE macro to
grab the next mbuf to send, and use IF_PREPEND if the card is busy
and we actually can't handle it right now.

The old code was first getting the mbuf by taking it from the queue
without using the macros, thus without locking, and without removing
it from the queue either.  It was later assuming that IF_DEQUEUE would
give him this same mbuf.

Tested by:	mich
This commit is contained in:
mux 2003-06-26 13:27:44 +00:00
parent eb5358bc43
commit 77cccd32e5

View File

@ -497,7 +497,7 @@ ep_if_start(ifp)
startagain:
/* Sneak a peek at the next packet */
m = ifp->if_snd.ifq_head;
IF_DEQUEUE(&ifp->if_snd, m);
if (m == 0) {
return;
}
@ -514,8 +514,7 @@ ep_if_start(ifp)
if (len + pad > ETHER_MAX_LEN) {
/* packet is obviously too large: toss it */
++ifp->if_oerrors;
IF_DEQUEUE(&ifp->if_snd, m);
m_freem(m);
m_freem(top);
goto readcheck;
}
if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
@ -524,21 +523,20 @@ ep_if_start(ifp)
/* make sure */
if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
ifp->if_flags |= IFF_OACTIVE;
IF_PREPEND(&ifp->if_snd, top);
return;
}
} else {
outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE);
}
IF_DEQUEUE(&ifp->if_snd, m);
s = splhigh();
outw(BASE + EP_W1_TX_PIO_WR_1, len);
outw(BASE + EP_W1_TX_PIO_WR_1, 0x0); /* Second dword meaningless */
if (EP_FTST(sc, F_ACCESS_32_BITS)) {
for (top = m; m != 0; m = m->m_next) {
for (m = top; m != 0; m = m->m_next) {
if (m->m_len > 3)
outsl(BASE + EP_W1_TX_PIO_WR_1,
mtod(m, caddr_t), m->m_len / 4);
@ -547,7 +545,7 @@ ep_if_start(ifp)
mtod(m, caddr_t) + (m->m_len & (~3)), m->m_len & 3);
}
} else {
for (top = m; m != 0; m = m->m_next) {
for (m = top; m != 0; m = m->m_next) {
if (m->m_len > 1)
outsw(BASE + EP_W1_TX_PIO_WR_1,
mtod(m, caddr_t), m->m_len / 2);