summaryrefslogtreecommitdiffstats
path: root/sys/dev/ep/if_ep.c
diff options
context:
space:
mode:
authormux <mux@FreeBSD.org>2003-06-26 13:27:44 +0000
committermux <mux@FreeBSD.org>2003-06-26 13:27:44 +0000
commit77cccd32e5087adad2de0d663d04dc300add1571 (patch)
tree751b26a4666524b14609d1b7c9737d5ca46cffeb /sys/dev/ep/if_ep.c
parenteb5358bc434ed50b7de78727744ec72d27d0d97d (diff)
downloadFreeBSD-src-77cccd32e5087adad2de0d663d04dc300add1571.zip
FreeBSD-src-77cccd32e5087adad2de0d663d04dc300add1571.tar.gz
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
Diffstat (limited to 'sys/dev/ep/if_ep.c')
-rw-r--r--sys/dev/ep/if_ep.c12
1 files changed, 5 insertions, 7 deletions
diff --git a/sys/dev/ep/if_ep.c b/sys/dev/ep/if_ep.c
index fd3d90a..b607bf5 100644
--- a/sys/dev/ep/if_ep.c
+++ b/sys/dev/ep/if_ep.c
@@ -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 @@ startagain:
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 @@ startagain:
/* 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 @@ startagain:
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);
OpenPOWER on IntegriCloud