diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2013-03-17 10:17:55 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2013-03-17 10:17:55 +0000 |
commit | ea6c118a931140b92dd43f64f1ab8816c69307de (patch) | |
tree | 1627dcda654e10f33a87e537b35abfdd52dd57dc /sys/dev/pci | |
parent | d3224777b02fb2430c984ccf85a921db8eb2501a (diff) |
- Sync some of the stats counter code to be closer to the FreeBSD code,
but no functional change.
- Add a workaround for BCM5717 / BCM5718 / BCM5719 A0 and BCM5720 A0 chipsets
to not count the interface input drops counter for input errors due to HW
errata.
From FreeBSD
ok sthen@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_bge.c | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c index c22b17082c7..1e193ecc6d5 100644 --- a/sys/dev/pci/if_bge.c +++ b/sys/dev/pci/if_bge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bge.c,v 1.323 2013/03/11 01:12:40 dlg Exp $ */ +/* $OpenBSD: if_bge.c,v 1.324 2013/03/17 10:17:54 brad Exp $ */ /* * Copyright (c) 2001 Wind River Systems @@ -3503,13 +3503,38 @@ bge_stats_update_regs(struct bge_softc *sc) { struct ifnet *ifp = &sc->arpcom.ac_if; - ifp->if_collisions += CSR_READ_4(sc, BGE_MAC_STATS + + sc->bge_tx_collisions += CSR_READ_4(sc, BGE_MAC_STATS + offsetof(struct bge_mac_stats_regs, etherStatsCollisions)); - sc->bge_rx_discards += CSR_READ_4(sc, BGE_RXLP_LOCSTAT_IFIN_DROPS); - sc->bge_rx_inerrors += CSR_READ_4(sc, BGE_RXLP_LOCSTAT_IFIN_ERRORS); sc->bge_rx_overruns += CSR_READ_4(sc, BGE_RXLP_LOCSTAT_OUT_OF_BDS); + /* + * XXX + * Unlike other controllers, BGE_RXLP_LOCSTAT_IFIN_DROPS + * counter of BCM5717, BCM5718, BCM5719 A0 and BCM5720 A0 + * includes number of unwanted multicast frames. This comes + * from silicon bug and known workaround to get rough(not + * exact) counter is to enable interrupt on MBUF low water + * attention. This can be accomplished by setting + * BGE_HCCMODE_ATTN bit of BGE_HCC_MODE, + * BGE_BMANMODE_LOMBUF_ATTN bit of BGE_BMAN_MODE and + * BGE_MODECTL_FLOWCTL_ATTN_INTR bit of BGE_MODE_CTL. + * However that change would generate more interrupts and + * there are still possibilities of losing multiple frames + * during BGE_MODECTL_FLOWCTL_ATTN_INTR interrupt handling. + * Given that the workaround still would not get correct + * counter I don't think it's worth to implement it. So + * ignore reading the counter on controllers that have the + * silicon bug. + */ + if (BGE_ASICREV(sc->bge_chipid) != BGE_ASICREV_BCM5717 && + sc->bge_chipid != BGE_CHIPID_BCM5719_A0 && + sc->bge_chipid != BGE_CHIPID_BCM5720_A0) + sc->bge_rx_discards += CSR_READ_4(sc, BGE_RXLP_LOCSTAT_IFIN_DROPS); + + sc->bge_rx_inerrors += CSR_READ_4(sc, BGE_RXLP_LOCSTAT_IFIN_ERRORS); + + ifp->if_collisions = sc->bge_tx_collisions; ifp->if_ierrors = sc->bge_rx_discards + sc->bge_rx_inerrors + sc->bge_rx_overruns; } @@ -3528,18 +3553,16 @@ bge_stats_update(struct bge_softc *sc) ifp->if_collisions += (u_int32_t)(cnt - sc->bge_tx_collisions); sc->bge_tx_collisions = cnt; + cnt = READ_STAT(sc, stats, nicNoMoreRxBDs.bge_addr_lo); + ifp->if_ierrors += (uint32_t)(cnt - sc->bge_rx_overruns); + sc->bge_rx_overruns = cnt; + cnt = READ_STAT(sc, stats, ifInErrors.bge_addr_lo); + ifp->if_ierrors += (uint32_t)(cnt - sc->bge_rx_inerrors); + sc->bge_rx_inerrors = cnt; cnt = READ_STAT(sc, stats, ifInDiscards.bge_addr_lo); ifp->if_ierrors += (u_int32_t)(cnt - sc->bge_rx_discards); sc->bge_rx_discards = cnt; - cnt = READ_STAT(sc, stats, ifInErrors.bge_addr_lo); - ifp->if_ierrors += (u_int32_t)(cnt - sc->bge_rx_inerrors); - sc->bge_rx_inerrors = cnt; - - cnt = READ_STAT(sc, stats, nicNoMoreRxBDs.bge_addr_lo); - ifp->if_ierrors += (u_int32_t)(cnt - sc->bge_rx_overruns); - sc->bge_rx_overruns = cnt; - cnt = READ_STAT(sc, stats, txstats.ifOutDiscards.bge_addr_lo); ifp->if_oerrors += (u_int32_t)(cnt - sc->bge_tx_discards); sc->bge_tx_discards = cnt; |