summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_em.c
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2005-10-16 17:32:38 +0000
committerBrad Smith <brad@cvs.openbsd.org>2005-10-16 17:32:38 +0000
commit6d0354e9578ae582c44b1ded2da413e34e6991cc (patch)
tree1a4e4740a62791f53e39c7eba573f440d81d502c /sys/dev/pci/if_em.c
parent14acfbd41844511b35997673c66a160f17a17d13 (diff)
While in em_process_receive_interrupts() processing the packet em_init()
may be called (either from em_watchdog() from softclock interrupt or from ifconfig). em_init() resets the card, in particular it sets sc->next_rx_desc_to_check to 0 and resets hardware RX Head and Tail descriptor pointers. The loop in em_process_receive_interrupts() does not expect these things to change, and a mess may result. >From glebius FreeBSD ok krw@
Diffstat (limited to 'sys/dev/pci/if_em.c')
-rw-r--r--sys/dev/pci/if_em.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
index 656ce1d3f09..45dd16d1d0e 100644
--- a/sys/dev/pci/if_em.c
+++ b/sys/dev/pci/if_em.c
@@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
-/* $OpenBSD: if_em.c,v 1.77 2005/10/15 14:43:36 brad Exp $ */
+/* $OpenBSD: if_em.c,v 1.78 2005/10/16 17:32:37 brad Exp $ */
/* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */
#include <dev/pci/if_em.h>
@@ -2320,6 +2320,7 @@ em_process_receive_interrupts(struct em_softc *sc, int count)
}
while ((current_desc->status & E1000_RXD_STAT_DD) && (count != 0)) {
+ struct mbuf *m = NULL;
mp = sc->rx_buffer_area[i].m_head;
bus_dmamap_sync(sc->rxtag, sc->rx_buffer_area[i].map,
@@ -2455,18 +2456,9 @@ em_process_receive_interrupts(struct em_softc *sc, int count)
if (eop) {
sc->fmp->m_pkthdr.rcvif = ifp;
ifp->if_ipackets++;
-
-#if NBPFILTER > 0
- /*
- * Handle BPF listeners. Let the BPF
- * user see the packet.
- */
- if (ifp->if_bpf)
- bpf_mtap(ifp->if_bpf, sc->fmp);
-#endif
em_receive_checksum(sc, current_desc,
sc->fmp);
- ether_input_mbuf(ifp, sc->fmp);
+ m = sc->fmp;
sc->fmp = NULL;
sc->lmp = NULL;
}
@@ -2486,11 +2478,25 @@ em_process_receive_interrupts(struct em_softc *sc, int count)
E1000_WRITE_REG(&sc->hw, RDT, i);
/* Advance our pointers to the next descriptor */
- if (++i == sc->num_rx_desc) {
+ if (++i == sc->num_rx_desc)
i = 0;
- current_desc = sc->rx_desc_base;
- } else
- current_desc++;
+ if (m != NULL) {
+ sc->next_rx_desc_to_check = i;
+
+#if NBPFILTER > 0
+ /*
+ * Handle BPF listeners. Let the BPF
+ * user see the packet.
+ */
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m);
+#endif
+
+ ether_input_mbuf(ifp, m);
+
+ i = sc->next_rx_desc_to_check;
+ }
+ current_desc = &sc->rx_desc_base[i];
}
sc->next_rx_desc_to_check = i;
}