diff options
| author | msaitoh <msaitoh@NetBSD.org> | 2019-03-27 03:29:50 +0000 |
|---|---|---|
| committer | msaitoh <msaitoh@NetBSD.org> | 2019-03-27 03:29:50 +0000 |
| commit | a6d2fdfa0f893c6ff00f94d773fd2d427d209020 (patch) | |
| tree | 738dcbe68fd7d189a67fca998dccf130111ae1e5 /sys/dev | |
| parent | 5810085705388eccf4331a2ceb7019aeefdb894a (diff) | |
Apply OpenBSD rev. 1.94:
> ido not disable interrupts in the isr and then enable them again
> when leaving. when you're handling an interrupt it is masked.
> whacking the chip is work for no gain.
>
> 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@
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/pci/if_bnx.c | 69 |
1 files changed, 25 insertions, 44 deletions
diff --git a/sys/dev/pci/if_bnx.c b/sys/dev/pci/if_bnx.c index 29bb58a13fe..28173e762fa 100644 --- a/sys/dev/pci/if_bnx.c +++ b/sys/dev/pci/if_bnx.c @@ -1,5 +1,5 @@ -/* $NetBSD: if_bnx.c,v 1.69 2019/03/27 03:10:39 msaitoh Exp $ */ -/* $OpenBSD: if_bnx.c,v 1.85 2009/11/09 14:32:41 dlg Exp $ */ +/* $NetBSD: if_bnx.c,v 1.70 2019/03/27 03:29:50 msaitoh Exp $ */ +/* $OpenBSD: if_bnx.c,v 1.94 2011/04/18 04:27:31 dlg Exp $ */ /*- * Copyright (c) 2006-2010 Broadcom Corporation @@ -35,7 +35,7 @@ #if 0 __FBSDID("$FreeBSD: src/sys/dev/bce/if_bce.c,v 1.3 2006/04/13 14:12:26 ru Exp $"); #endif -__KERNEL_RCSID(0, "$NetBSD: if_bnx.c,v 1.69 2019/03/27 03:10:39 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_bnx.c,v 1.70 2019/03/27 03:29:50 msaitoh Exp $"); /* * The following controllers are supported by this driver: @@ -5264,14 +5264,12 @@ bnx_watchdog(struct ifnet *ifp) int bnx_intr(void *xsc) { - struct bnx_softc *sc; - struct ifnet *ifp; + struct bnx_softc *sc = xsc; + struct ifnet *ifp = &sc->bnx_ec.ec_if; uint32_t status_attn_bits; + uint16_t status_idx; const struct status_block *sblk; - - sc = xsc; - - ifp = &sc->bnx_ec.ec_if; + int rv = 0; if (!device_is_active(sc->bnx_dev) || (ifp->if_flags & IFF_RUNNING) == 0) @@ -5282,25 +5280,23 @@ bnx_intr(void *xsc) bus_dmamap_sync(sc->bnx_dmatag, sc->status_map, 0, sc->status_map->dm_mapsize, BUS_DMASYNC_POSTREAD); + sblk = sc->status_block; /* * If the hardware status block index * matches the last value read by the * driver and we haven't asserted our * interrupt then there's nothing to do. */ - if ((sc->status_block->status_idx == sc->last_status_idx) && - (REG_RD(sc, BNX_PCICFG_MISC_STATUS) & - BNX_PCICFG_MISC_STATUS_INTA_VALUE)) - return 0; + status_idx = sblk->status_idx; + if ((status_idx != sc->last_status_idx) || + !ISSET(REG_RD(sc, BNX_PCICFG_MISC_STATUS), + BNX_PCICFG_MISC_STATUS_INTA_VALUE)) { + rv = 1; - /* Ack the interrupt and stop others from occurring. */ - REG_WR(sc, BNX_PCICFG_INT_ACK_CMD, - BNX_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | - BNX_PCICFG_INT_ACK_CMD_MASK_INT); + /* Ack the interrupt */ + REG_WR(sc, BNX_PCICFG_INT_ACK_CMD, + BNX_PCICFG_INT_ACK_CMD_INDEX_VALID | status_idx); - /* Keep processing data as long as there is work to do. */ - for (;;) { - sblk = sc->status_block; status_attn_bits = sblk->status_attn_bits; DBRUNIF(DB_RANDOMTRUE(bnx_debug_unexpected_attention), @@ -5325,10 +5321,10 @@ bnx_intr(void *xsc) DBRUN(BNX_FATAL, if (bnx_debug_unexpected_attention == 0) - bnx_breakpoint(sc)); + bnx_breakpoint(sc)); bnx_init(ifp); - return 1; + goto out; } /* Check for any completed RX frames. */ @@ -5343,35 +5339,20 @@ bnx_intr(void *xsc) * Save the status block index value for use during the * next interrupt. */ - sc->last_status_idx = sblk->status_idx; + sc->last_status_idx = status_idx; - /* Prevent speculative reads from getting ahead of the - * status block. - */ - bus_space_barrier(sc->bnx_btag, sc->bnx_bhandle, 0, 0, - BUS_SPACE_BARRIER_READ); - - /* If there's no work left then exit the isr. */ - if ((sblk->status_rx_quick_consumer_index0 == - sc->hw_rx_cons) && - (sblk->status_tx_quick_consumer_index0 == sc->hw_tx_cons)) - break; + /* Start moving packets again */ + if (ifp->if_flags & IFF_RUNNING && + !IFQ_IS_EMPTY(&ifp->if_snd)) + if_schedule_deferred_start(ifp); } +out: bus_dmamap_sync(sc->bnx_dmatag, sc->status_map, 0, sc->status_map->dm_mapsize, BUS_DMASYNC_PREREAD); - /* Re-enable interrupts. */ - REG_WR(sc, BNX_PCICFG_INT_ACK_CMD, - BNX_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx | - BNX_PCICFG_INT_ACK_CMD_MASK_INT); - REG_WR(sc, BNX_PCICFG_INT_ACK_CMD, - BNX_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx); - - /* Handle any frames that arrived while handling the interrupt. */ - if_schedule_deferred_start(ifp); - return 1; + return rv; } /****************************************************************************/ |
