diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2005-10-16 17:32:38 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2005-10-16 17:32:38 +0000 |
commit | 6d0354e9578ae582c44b1ded2da413e34e6991cc (patch) | |
tree | 1a4e4740a62791f53e39c7eba573f440d81d502c /sys/dev/pci/if_em.c | |
parent | 14acfbd41844511b35997673c66a160f17a17d13 (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.c | 36 |
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; } |