svn commit: r201865 - stable/7/sys/dev/vge
Pyun YongHyeon
yongari at FreeBSD.org
Sat Jan 9 00:08:16 UTC 2010
Author: yongari
Date: Sat Jan 9 00:08:15 2010
New Revision: 201865
URL: http://svn.freebsd.org/changeset/base/201865
Log:
MFC 200615:
Add hardware MAC statistics support. This statistics could be
extracted from dev.vge.%d.stats sysctl node.
Modified:
stable/7/sys/dev/vge/if_vge.c
stable/7/sys/dev/vge/if_vgereg.h
stable/7/sys/dev/vge/if_vgevar.h
Directory Properties:
stable/7/sys/ (props changed)
stable/7/sys/cddl/contrib/opensolaris/ (props changed)
stable/7/sys/contrib/dev/acpica/ (props changed)
stable/7/sys/contrib/pf/ (props changed)
Modified: stable/7/sys/dev/vge/if_vge.c
==============================================================================
--- stable/7/sys/dev/vge/if_vge.c Sat Jan 9 00:07:47 2010 (r201864)
+++ stable/7/sys/dev/vge/if_vge.c Sat Jan 9 00:08:15 2010 (r201865)
@@ -93,6 +93,7 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/socket.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -132,6 +133,13 @@ static int msi_disable = 0;
TUNABLE_INT("hw.vge.msi_disable", &msi_disable);
/*
+ * The SQE error counter of MIB seems to report bogus value.
+ * Vendor's workaround does not seem to work on PCIe based
+ * controllers. Disable it until we find better workaround.
+ */
+#undef VGE_ENABLE_SQEERR
+
+/*
* Various supported device vendors/types and their names.
*/
static struct vge_type vge_devs[] = {
@@ -183,7 +191,10 @@ static void vge_rxfilter(struct vge_soft
static void vge_setvlan(struct vge_softc *);
static void vge_start(struct ifnet *);
static void vge_start_locked(struct ifnet *);
+static void vge_stats_clear(struct vge_softc *);
+static void vge_stats_update(struct vge_softc *);
static void vge_stop(struct vge_softc *);
+static void vge_sysctl_node(struct vge_softc *);
static int vge_tx_list_init(struct vge_softc *);
static void vge_txeof(struct vge_softc *);
static void vge_watchdog(void *);
@@ -1060,6 +1071,7 @@ vge_attach(device_t dev)
else
sc->vge_phyaddr = CSR_READ_1(sc, VGE_MIICFG) &
VGE_MIICFG_PHYADDR;
+ vge_sysctl_node(sc);
error = vge_dma_alloc(sc);
if (error)
goto fail;
@@ -1700,7 +1712,6 @@ vge_poll (struct ifnet *ifp, enum poll_c
if (status & (VGE_ISR_RXOFLOW|VGE_ISR_RXNODESC)) {
vge_rxeof(sc, count);
- ifp->if_ierrors++;
CSR_WRITE_1(sc, VGE_RXQCSRS, VGE_RXQCSR_RUN);
CSR_WRITE_1(sc, VGE_RXQCSRS, VGE_RXQCSR_WAK);
}
@@ -2035,7 +2046,8 @@ vge_init_locked(struct vge_softc *sc)
return;
}
vge_tx_list_init(sc);
-
+ /* Clear MAC statistics. */
+ vge_stats_clear(sc);
/* Set our station address */
for (i = 0; i < ETHER_ADDR_LEN; i++)
CSR_WRITE_1(sc, VGE_PAR0 + i, IF_LLADDR(sc->vge_ifp)[i]);
@@ -2359,6 +2371,7 @@ vge_watchdog(void *arg)
sc = arg;
VGE_LOCK_ASSERT(sc);
+ vge_stats_update(sc);
callout_reset(&sc->vge_watchdog, hz, vge_watchdog, sc);
if (sc->vge_timer == 0 || --sc->vge_timer > 0)
return;
@@ -2397,6 +2410,7 @@ vge_stop(struct vge_softc *sc)
CSR_WRITE_1(sc, VGE_RXQCSRC, 0xFF);
CSR_WRITE_4(sc, VGE_RXDESC_ADDR_LO, 0);
+ vge_stats_update(sc);
VGE_CHAIN_RESET(sc);
vge_txeof(sc);
vge_freebufs(sc);
@@ -2470,3 +2484,223 @@ vge_shutdown(device_t dev)
return (0);
}
+
+#define VGE_SYSCTL_STAT_ADD32(c, h, n, p, d) \
+ SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d)
+
+static void
+vge_sysctl_node(struct vge_softc *sc)
+{
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid_list *child, *parent;
+ struct sysctl_oid *tree;
+ struct vge_hw_stats *stats;
+
+ stats = &sc->vge_stats;
+ ctx = device_get_sysctl_ctx(sc->vge_dev);
+ child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->vge_dev));
+ tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD,
+ NULL, "VGE statistics");
+ parent = SYSCTL_CHILDREN(tree);
+
+ /* Rx statistics. */
+ tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "rx", CTLFLAG_RD,
+ NULL, "RX MAC statistics");
+ child = SYSCTL_CHILDREN(tree);
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames",
+ &stats->rx_frames, "frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "good_frames",
+ &stats->rx_good_frames, "Good frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "fifo_oflows",
+ &stats->rx_fifo_oflows, "FIFO overflows");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "runts",
+ &stats->rx_runts, "Too short frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "runts_errs",
+ &stats->rx_runts_errs, "Too short frames with errors");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_64",
+ &stats->rx_pkts_64, "64 bytes frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_65_127",
+ &stats->rx_pkts_65_127, "65 to 127 bytes frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_128_255",
+ &stats->rx_pkts_128_255, "128 to 255 bytes frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_256_511",
+ &stats->rx_pkts_256_511, "256 to 511 bytes frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_512_1023",
+ &stats->rx_pkts_512_1023, "512 to 1023 bytes frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_1024_1518",
+ &stats->rx_pkts_1024_1518, "1024 to 1518 bytes frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_1519_max",
+ &stats->rx_pkts_1519_max, "1519 to max frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_1519_max_errs",
+ &stats->rx_pkts_1519_max_errs, "1519 to max frames with error");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_jumbo",
+ &stats->rx_jumbos, "Jumbo frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "crcerrs",
+ &stats->rx_crcerrs, "CRC errors");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "pause_frames",
+ &stats->rx_pause_frames, "CRC errors");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "align_errs",
+ &stats->rx_alignerrs, "Alignment errors");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "nobufs",
+ &stats->rx_nobufs, "Frames with no buffer event");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "sym_errs",
+ &stats->rx_symerrs, "Frames with symbol errors");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "len_errs",
+ &stats->rx_lenerrs, "Frames with length mismatched");
+
+ /* Tx statistics. */
+ tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "tx", CTLFLAG_RD,
+ NULL, "TX MAC statistics");
+ child = SYSCTL_CHILDREN(tree);
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "good_frames",
+ &stats->tx_good_frames, "Good frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_64",
+ &stats->tx_pkts_64, "64 bytes frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_65_127",
+ &stats->tx_pkts_65_127, "65 to 127 bytes frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_128_255",
+ &stats->tx_pkts_128_255, "128 to 255 bytes frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_256_511",
+ &stats->tx_pkts_256_511, "256 to 511 bytes frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_512_1023",
+ &stats->tx_pkts_512_1023, "512 to 1023 bytes frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_1024_1518",
+ &stats->tx_pkts_1024_1518, "1024 to 1518 bytes frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "frames_jumbo",
+ &stats->tx_jumbos, "Jumbo frames");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "colls",
+ &stats->tx_colls, "Collisions");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "late_colls",
+ &stats->tx_latecolls, "Late collisions");
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "pause_frames",
+ &stats->tx_pause, "Pause frames");
+#ifdef VGE_ENABLE_SQEERR
+ VGE_SYSCTL_STAT_ADD32(ctx, child, "sqeerrs",
+ &stats->tx_sqeerrs, "SQE errors");
+#endif
+ /* Clear MAC statistics. */
+ vge_stats_clear(sc);
+}
+
+#undef VGE_SYSCTL_STAT_ADD32
+
+static void
+vge_stats_clear(struct vge_softc *sc)
+{
+ int i;
+
+ VGE_LOCK_ASSERT(sc);
+
+ CSR_WRITE_1(sc, VGE_MIBCSR,
+ CSR_READ_1(sc, VGE_MIBCSR) | VGE_MIBCSR_FREEZE);
+ CSR_WRITE_1(sc, VGE_MIBCSR,
+ CSR_READ_1(sc, VGE_MIBCSR) | VGE_MIBCSR_CLR);
+ for (i = VGE_TIMEOUT; i > 0; i--) {
+ DELAY(1);
+ if ((CSR_READ_1(sc, VGE_MIBCSR) & VGE_MIBCSR_CLR) == 0)
+ break;
+ }
+ if (i == 0)
+ device_printf(sc->vge_dev, "MIB clear timed out!\n");
+ CSR_WRITE_1(sc, VGE_MIBCSR, CSR_READ_1(sc, VGE_MIBCSR) &
+ ~VGE_MIBCSR_FREEZE);
+}
+
+static void
+vge_stats_update(struct vge_softc *sc)
+{
+ struct vge_hw_stats *stats;
+ struct ifnet *ifp;
+ uint32_t mib[VGE_MIB_CNT], val;
+ int i;
+
+ VGE_LOCK_ASSERT(sc);
+
+ stats = &sc->vge_stats;
+ ifp = sc->vge_ifp;
+
+ CSR_WRITE_1(sc, VGE_MIBCSR,
+ CSR_READ_1(sc, VGE_MIBCSR) | VGE_MIBCSR_FLUSH);
+ for (i = VGE_TIMEOUT; i > 0; i--) {
+ DELAY(1);
+ if ((CSR_READ_1(sc, VGE_MIBCSR) & VGE_MIBCSR_FLUSH) == 0)
+ break;
+ }
+ if (i == 0) {
+ device_printf(sc->vge_dev, "MIB counter dump timed out!\n");
+ vge_stats_clear(sc);
+ return;
+ }
+
+ bzero(mib, sizeof(mib));
+reset_idx:
+ /* Set MIB read index to 0. */
+ CSR_WRITE_1(sc, VGE_MIBCSR,
+ CSR_READ_1(sc, VGE_MIBCSR) | VGE_MIBCSR_RINI);
+ for (i = 0; i < VGE_MIB_CNT; i++) {
+ val = CSR_READ_4(sc, VGE_MIBDATA);
+ if (i != VGE_MIB_DATA_IDX(val)) {
+ /* Reading interrupted. */
+ goto reset_idx;
+ }
+ mib[i] = val & VGE_MIB_DATA_MASK;
+ }
+
+ /* Rx stats. */
+ stats->rx_frames += mib[VGE_MIB_RX_FRAMES];
+ stats->rx_good_frames += mib[VGE_MIB_RX_GOOD_FRAMES];
+ stats->rx_fifo_oflows += mib[VGE_MIB_RX_FIFO_OVERRUNS];
+ stats->rx_runts += mib[VGE_MIB_RX_RUNTS];
+ stats->rx_runts_errs += mib[VGE_MIB_RX_RUNTS_ERRS];
+ stats->rx_pkts_64 += mib[VGE_MIB_RX_PKTS_64];
+ stats->rx_pkts_65_127 += mib[VGE_MIB_RX_PKTS_65_127];
+ stats->rx_pkts_128_255 += mib[VGE_MIB_RX_PKTS_128_255];
+ stats->rx_pkts_256_511 += mib[VGE_MIB_RX_PKTS_256_511];
+ stats->rx_pkts_512_1023 += mib[VGE_MIB_RX_PKTS_512_1023];
+ stats->rx_pkts_1024_1518 += mib[VGE_MIB_RX_PKTS_1024_1518];
+ stats->rx_pkts_1519_max += mib[VGE_MIB_RX_PKTS_1519_MAX];
+ stats->rx_pkts_1519_max_errs += mib[VGE_MIB_RX_PKTS_1519_MAX_ERRS];
+ stats->rx_jumbos += mib[VGE_MIB_RX_JUMBOS];
+ stats->rx_crcerrs += mib[VGE_MIB_RX_CRCERRS];
+ stats->rx_pause_frames += mib[VGE_MIB_RX_PAUSE];
+ stats->rx_alignerrs += mib[VGE_MIB_RX_ALIGNERRS];
+ stats->rx_nobufs += mib[VGE_MIB_RX_NOBUFS];
+ stats->rx_symerrs += mib[VGE_MIB_RX_SYMERRS];
+ stats->rx_lenerrs += mib[VGE_MIB_RX_LENERRS];
+
+ /* Tx stats. */
+ stats->tx_good_frames += mib[VGE_MIB_TX_GOOD_FRAMES];
+ stats->tx_pkts_64 += mib[VGE_MIB_TX_PKTS_64];
+ stats->tx_pkts_65_127 += mib[VGE_MIB_TX_PKTS_65_127];
+ stats->tx_pkts_128_255 += mib[VGE_MIB_TX_PKTS_128_255];
+ stats->tx_pkts_256_511 += mib[VGE_MIB_TX_PKTS_256_511];
+ stats->tx_pkts_512_1023 += mib[VGE_MIB_TX_PKTS_512_1023];
+ stats->tx_pkts_1024_1518 += mib[VGE_MIB_TX_PKTS_1024_1518];
+ stats->tx_jumbos += mib[VGE_MIB_TX_JUMBOS];
+ stats->tx_colls += mib[VGE_MIB_TX_COLLS];
+ stats->tx_pause += mib[VGE_MIB_TX_PAUSE];
+#ifdef VGE_ENABLE_SQEERR
+ stats->tx_sqeerrs += mib[VGE_MIB_TX_SQEERRS];
+#endif
+ stats->tx_latecolls += mib[VGE_MIB_TX_LATECOLLS];
+
+ /* Update counters in ifnet. */
+ ifp->if_opackets += mib[VGE_MIB_TX_GOOD_FRAMES];
+
+ ifp->if_collisions += mib[VGE_MIB_TX_COLLS] +
+ mib[VGE_MIB_TX_LATECOLLS];
+
+ ifp->if_oerrors += mib[VGE_MIB_TX_COLLS] +
+ mib[VGE_MIB_TX_LATECOLLS];
+
+ ifp->if_ipackets += mib[VGE_MIB_RX_GOOD_FRAMES];
+
+ ifp->if_ierrors += mib[VGE_MIB_RX_FIFO_OVERRUNS] +
+ mib[VGE_MIB_RX_RUNTS] +
+ mib[VGE_MIB_RX_RUNTS_ERRS] +
+ mib[VGE_MIB_RX_CRCERRS] +
+ mib[VGE_MIB_RX_ALIGNERRS] +
+ mib[VGE_MIB_RX_NOBUFS] +
+ mib[VGE_MIB_RX_SYMERRS] +
+ mib[VGE_MIB_RX_LENERRS];
+}
Modified: stable/7/sys/dev/vge/if_vgereg.h
==============================================================================
--- stable/7/sys/dev/vge/if_vgereg.h Sat Jan 9 00:07:47 2010 (r201864)
+++ stable/7/sys/dev/vge/if_vgereg.h Sat Jan 9 00:08:15 2010 (r201865)
@@ -301,7 +301,7 @@
VGE_ISR_RXOFLOW|VGE_ISR_PHYINT| \
VGE_ISR_LINKSTS|VGE_ISR_RXNODESC| \
VGE_ISR_RXDMA_STALL|VGE_ISR_TXDMA_STALL| \
- VGE_ISR_MIBOFLOW|VGE_ISR_TIMER0)
+ VGE_ISR_TIMER0)
/* Interrupt mask register */
@@ -543,6 +543,54 @@
#define VGE_TXBLOCK_128PKTS 0x08
#define VGE_TXBLOCK_8PKTS 0x0C
+/* MIB control/status register */
+#define VGE_MIBCSR_CLR 0x01
+#define VGE_MIBCSR_RINI 0x02
+#define VGE_MIBCSR_FLUSH 0x04
+#define VGE_MIBCSR_FREEZE 0x08
+#define VGE_MIBCSR_HI_80 0x00
+#define VGE_MIBCSR_HI_C0 0x10
+#define VGE_MIBCSR_BISTGO 0x40
+#define VGE_MIBCSR_BISTOK 0x80
+
+/* MIB data index. */
+#define VGE_MIB_RX_FRAMES 0
+#define VGE_MIB_RX_GOOD_FRAMES 1
+#define VGE_MIB_TX_GOOD_FRAMES 2
+#define VGE_MIB_RX_FIFO_OVERRUNS 3
+#define VGE_MIB_RX_RUNTS 4
+#define VGE_MIB_RX_RUNTS_ERRS 5
+#define VGE_MIB_RX_PKTS_64 6
+#define VGE_MIB_TX_PKTS_64 7
+#define VGE_MIB_RX_PKTS_65_127 8
+#define VGE_MIB_TX_PKTS_65_127 9
+#define VGE_MIB_RX_PKTS_128_255 10
+#define VGE_MIB_TX_PKTS_128_255 11
+#define VGE_MIB_RX_PKTS_256_511 12
+#define VGE_MIB_TX_PKTS_256_511 13
+#define VGE_MIB_RX_PKTS_512_1023 14
+#define VGE_MIB_TX_PKTS_512_1023 15
+#define VGE_MIB_RX_PKTS_1024_1518 16
+#define VGE_MIB_TX_PKTS_1024_1518 17
+#define VGE_MIB_TX_COLLS 18
+#define VGE_MIB_RX_CRCERRS 19
+#define VGE_MIB_RX_JUMBOS 20
+#define VGE_MIB_TX_JUMBOS 21
+#define VGE_MIB_RX_PAUSE 22
+#define VGE_MIB_TX_PAUSE 23
+#define VGE_MIB_RX_ALIGNERRS 24
+#define VGE_MIB_RX_PKTS_1519_MAX 25
+#define VGE_MIB_RX_PKTS_1519_MAX_ERRS 26
+#define VGE_MIB_TX_SQEERRS 27
+#define VGE_MIB_RX_NOBUFS 28
+#define VGE_MIB_RX_SYMERRS 29
+#define VGE_MIB_RX_LENERRS 30
+#define VGE_MIB_TX_LATECOLLS 31
+
+#define VGE_MIB_CNT (VGE_MIB_TX_LATECOLLS - VGE_MIB_RX_FRAMES + 1)
+#define VGE_MIB_DATA_MASK 0x00FFFFFF
+#define VGE_MIB_DATA_IDX(x) ((x) >> 24)
+
/* EEPROM control/status register */
#define VGE_EECSR_EDO 0x01 /* data out pin */
Modified: stable/7/sys/dev/vge/if_vgevar.h
==============================================================================
--- stable/7/sys/dev/vge/if_vgevar.h Sat Jan 9 00:07:47 2010 (r201864)
+++ stable/7/sys/dev/vge/if_vgevar.h Sat Jan 9 00:08:15 2010 (r201865)
@@ -130,6 +130,42 @@ struct vge_ring_data {
bus_addr_t vge_rx_ring_paddr;
};
+struct vge_hw_stats {
+ uint32_t rx_frames;
+ uint32_t rx_good_frames;
+ uint32_t rx_fifo_oflows;
+ uint32_t rx_runts;
+ uint32_t rx_runts_errs;
+ uint32_t rx_pkts_64;
+ uint32_t rx_pkts_65_127;
+ uint32_t rx_pkts_128_255;
+ uint32_t rx_pkts_256_511;
+ uint32_t rx_pkts_512_1023;
+ uint32_t rx_pkts_1024_1518;
+ uint32_t rx_pkts_1519_max;
+ uint32_t rx_pkts_1519_max_errs;
+ uint32_t rx_jumbos;
+ uint32_t rx_crcerrs;
+ uint32_t rx_pause_frames;
+ uint32_t rx_alignerrs;
+ uint32_t rx_nobufs;
+ uint32_t rx_symerrs;
+ uint32_t rx_lenerrs;
+
+ uint32_t tx_good_frames;
+ uint32_t tx_pkts_64;
+ uint32_t tx_pkts_65_127;
+ uint32_t tx_pkts_128_255;
+ uint32_t tx_pkts_256_511;
+ uint32_t tx_pkts_512_1023;
+ uint32_t tx_pkts_1024_1518;
+ uint32_t tx_jumbos;
+ uint32_t tx_colls;
+ uint32_t tx_pause;
+ uint32_t tx_sqeerrs;
+ uint32_t tx_latecolls;
+};
+
struct vge_softc {
struct ifnet *vge_ifp; /* interface info */
device_t vge_dev;
@@ -152,6 +188,7 @@ struct vge_softc {
struct vge_chain_data vge_cdata;
struct vge_ring_data vge_rdata;
+ struct vge_hw_stats vge_stats;
int suspended; /* 0 = normal 1 = suspended */
};
More information about the svn-src-all
mailing list