summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2013-03-17 10:17:55 +0000
committerBrad Smith <brad@cvs.openbsd.org>2013-03-17 10:17:55 +0000
commitea6c118a931140b92dd43f64f1ab8816c69307de (patch)
tree1627dcda654e10f33a87e537b35abfdd52dd57dc /sys/dev/pci
parentd3224777b02fb2430c984ccf85a921db8eb2501a (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.c47
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;