summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2011-04-13 00:19:01 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2011-04-13 00:19:01 +0000
commita0766b9f2117a2b3c07db4e6982d4afebeb461aa (patch)
tree3fe6afe5fa87208ded9bcf685b6afb60c5f00848 /sys/dev
parentd17616342566560120bb802c9a72bac62dc69a22 (diff)
modify the interrupt handler so it only processes the rings once,
rather than looping over them until it runs out of work to do. looping in the isr is bad for several reasons: firstly, the chip does interrupt mitigation so you have a decent/predictable amount of work to do in the isr. your first loop will do that chunk of work (ie, it pulls off 50ish packets), and then the successive looping aggressively pull one or two packets off the rx ring. these extra loops work against the benefit that interrupt mitigation provides. bus space reads are slow. we should avoid doing them where possible (but we should always do them when necessary). doing the loop 5 times per isr works against the mclgeti semantics. it knows a nic is busy and therefore needs more rx descriptors by watching to see when the nic uses all of its descriptors between interrupts. if we're aggressively pulling packets off by looping in the isr then we're skewing this check. ok deraadt@ claudio@ this is like src/sys/dev/pci/if_ix.c r1.50.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_em.c72
1 files changed, 32 insertions, 40 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
index 3f64601240b..f9b746f7677 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.253 2011/04/05 20:24:32 jsg Exp $ */
+/* $OpenBSD: if_em.c,v 1.254 2011/04/13 00:19:00 dlg Exp $ */
/* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */
#include <dev/pci/if_em.h>
@@ -820,54 +820,46 @@ em_init(void *arg)
int
em_intr(void *arg)
{
- struct em_softc *sc = arg;
- struct ifnet *ifp;
+ struct em_softc *sc = arg;
+ struct ifnet *ifp = &sc->interface_data.ac_if;
u_int32_t reg_icr, test_icr;
- int claimed = 0;
- int refill;
+ int refill = 0;
- ifp = &sc->interface_data.ac_if;
-
- for (;;) {
- test_icr = reg_icr = E1000_READ_REG(&sc->hw, ICR);
- if (sc->hw.mac_type >= em_82571)
- test_icr = (reg_icr & E1000_ICR_INT_ASSERTED);
- if (!test_icr)
- break;
-
- claimed = 1;
- refill = 0;
+ test_icr = reg_icr = E1000_READ_REG(&sc->hw, ICR);
+ if (sc->hw.mac_type >= em_82571)
+ test_icr = (reg_icr & E1000_ICR_INT_ASSERTED);
+ if (!test_icr)
+ return (0);
- if (ifp->if_flags & IFF_RUNNING) {
- em_rxeof(sc, -1);
- em_txeof(sc);
- refill = 1;
- }
+ if (ifp->if_flags & IFF_RUNNING) {
+ em_rxeof(sc, -1);
+ em_txeof(sc);
+ if (!IFQ_IS_EMPTY(&ifp->if_snd))
+ em_start(ifp);
- /* Link status change */
- if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
- timeout_del(&sc->timer_handle);
- sc->hw.get_link_status = 1;
- em_check_for_link(&sc->hw);
- em_update_link_status(sc);
- timeout_add_sec(&sc->timer_handle, 1);
- }
+ refill = 1;
+ }
- if (reg_icr & E1000_ICR_RXO) {
- sc->rx_overruns++;
- refill = 1;
- }
+ /* Link status change */
+ if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+ timeout_del(&sc->timer_handle);
+ sc->hw.get_link_status = 1;
+ em_check_for_link(&sc->hw);
+ em_update_link_status(sc);
+ timeout_add_sec(&sc->timer_handle, 1);
+ }
- if (refill && em_rxfill(sc)) {
- /* Advance the Rx Queue #0 "Tail Pointer". */
- E1000_WRITE_REG(&sc->hw, RDT, sc->last_rx_desc_filled);
- }
+ if (reg_icr & E1000_ICR_RXO) {
+ sc->rx_overruns++;
+ refill = 1;
}
- if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
- em_start(ifp);
+ if (refill && em_rxfill(sc)) {
+ /* Advance the Rx Queue #0 "Tail Pointer". */
+ E1000_WRITE_REG(&sc->hw, RDT, sc->last_rx_desc_filled);
+ }
- return (claimed);
+ return (1);
}
/*********************************************************************