Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 7 Dec 2011 21:46:09 +0000 (UTC)
From:      Pyun YongHyeon <yongari@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r228332 - head/sys/dev/et
Message-ID:  <201112072146.pB7Lk9L8057126@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: yongari
Date: Wed Dec  7 21:46:09 2011
New Revision: 228332
URL: http://svn.freebsd.org/changeset/base/228332

Log:
  Implement hardware MAC statistics counter.  Counters could be
  queried with dev.et.%d.stats sysctl node where %d is an instance of
  device.

Modified:
  head/sys/dev/et/if_et.c
  head/sys/dev/et/if_etreg.h
  head/sys/dev/et/if_etvar.h

Modified: head/sys/dev/et/if_et.c
==============================================================================
--- head/sys/dev/et/if_et.c	Wed Dec  7 21:29:51 2011	(r228331)
+++ head/sys/dev/et/if_et.c	Wed Dec  7 21:46:09 2011	(r228332)
@@ -146,6 +146,7 @@ static int	et_bus_config(struct et_softc
 static void	et_get_eaddr(device_t, uint8_t[]);
 static void	et_setmulti(struct et_softc *);
 static void	et_tick(void *);
+static void	et_stats_update(struct et_softc *);
 
 static const struct et_dev {
 	uint16_t	vid;
@@ -635,6 +636,7 @@ et_stop(struct et_softc *sc)
 
 	et_stop_rxdma(sc);
 	et_stop_txdma(sc);
+	et_stats_update(sc);
 
 	et_free_tx_ring(sc);
 	et_free_rx_ring(sc);
@@ -2049,7 +2051,6 @@ et_rxeof(struct et_softc *sc)
 		m = rbd->rbd_buf[buf_idx].rb_mbuf;
 		if ((rxst_info1 & ET_RXST_INFO1_OK) == 0){
 			/* Discard errored frame. */
-			ifp->if_ierrors++;
 			rbd->rbd_discard(rbd, buf_idx);
 		} else if (rbd->rbd_newbuf(rbd, buf_idx) != 0) {
 			/* No available mbufs, discard it. */
@@ -2063,7 +2064,6 @@ et_rxeof(struct et_softc *sc)
 			} else {
 				m->m_pkthdr.len = m->m_len = buflen;
 				m->m_pkthdr.rcvif = ifp;
-				ifp->if_ipackets++;
 				ET_UNLOCK(sc);
 				ifp->if_input(ifp, m);
 				ET_LOCK(sc);
@@ -2229,7 +2229,6 @@ et_txeof(struct et_softc *sc)
 			bus_dmamap_unload(sc->sc_tx_tag, tb->tb_dmap);
 			m_freem(tb->tb_mbuf);
 			tb->tb_mbuf = NULL;
-			ifp->if_opackets++;
 		}
 
 		if (++tbd->tbd_start_index == ET_TX_NDESC) {
@@ -2259,6 +2258,7 @@ et_tick(void *xsc)
 	mii = device_get_softc(sc->sc_miibus);
 
 	mii_tick(mii);
+	et_stats_update(sc);
 	if (et_watchdog(sc) == EJUSTRETURN)
 		return;
 	callout_reset(&sc->sc_tick, hz, et_tick, sc);
@@ -2371,6 +2371,11 @@ et_newbuf_hdr(struct et_rxbuf_data *rbd,
 	return (0);
 }
 
+#define	ET_SYSCTL_STAT_ADD32(c, h, n, p, d)	\
+	    SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d)
+#define	ET_SYSCTL_STAT_ADD64(c, h, n, p, d)	\
+	    SYSCTL_ADD_UQUAD(c, h, OID_AUTO, n, CTLFLAG_RD, p, d)
+
 /*
  * Create sysctl tree
  */
@@ -2378,7 +2383,9 @@ static void
 et_add_sysctls(struct et_softc * sc)
 {
 	struct sysctl_ctx_list *ctx;
-	struct sysctl_oid_list *children;
+	struct sysctl_oid_list *children, *parent;
+	struct sysctl_oid *tree;
+	struct et_hw_stats *stats;
 
 	ctx = device_get_sysctl_ctx(sc->dev);
 	children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
@@ -2394,8 +2401,116 @@ et_add_sysctls(struct et_softc * sc)
 	    "TX IM, # segments per TX interrupt");
 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "timer",
 	    CTLFLAG_RW, &sc->sc_timer, 0, "TX timer");
+
+	tree = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats", CTLFLAG_RD,
+	    NULL, "ET statistics");
+        parent = SYSCTL_CHILDREN(tree);
+
+	/* TX/RX statistics. */
+	stats = &sc->sc_stats;
+	ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_64", &stats->pkts_64,
+	    "0 to 64 bytes frames");
+	ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_65_127", &stats->pkts_65,
+	    "65 to 127 bytes frames");
+	ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_128_255", &stats->pkts_128,
+	    "128 to 255 bytes frames");
+	ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_256_511", &stats->pkts_256,
+	    "256 to 511 bytes frames");
+	ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_512_1023", &stats->pkts_512,
+	    "512 to 1023 bytes frames");
+	ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_1024_1518", &stats->pkts_1024,
+	    "1024 to 1518 bytes frames");
+	ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_1519_1522", &stats->pkts_1519,
+	    "1519 to 1522 bytes frames");
+
+	/* RX statistics. */
+	tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "rx", CTLFLAG_RD,
+	    NULL, "RX MAC statistics");
+	children = SYSCTL_CHILDREN(tree);
+	ET_SYSCTL_STAT_ADD64(ctx, children, "bytes",
+	    &stats->rx_bytes, "Good bytes");
+	ET_SYSCTL_STAT_ADD64(ctx, children, "frames",
+	    &stats->rx_frames, "Good frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "crc_errs",
+	    &stats->rx_crcerrs, "CRC errors");
+	ET_SYSCTL_STAT_ADD64(ctx, children, "mcast_frames",
+	    &stats->rx_mcast, "Multicast frames");
+	ET_SYSCTL_STAT_ADD64(ctx, children, "bcast_frames",
+	    &stats->rx_bcast, "Broadcast frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "control",
+	    &stats->rx_control, "Control frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "pause",
+	    &stats->rx_pause, "Pause frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "unknown_control",
+	    &stats->rx_unknown_control, "Unknown control frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "align_errs",
+	    &stats->rx_alignerrs, "Alignment errors");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "len_errs",
+	    &stats->rx_lenerrs, "Frames with length mismatched");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "code_errs",
+	    &stats->rx_codeerrs, "Frames with code error");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "cs_errs",
+	    &stats->rx_cserrs, "Frames with carrier sense error");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "runts",
+	    &stats->rx_runts, "Too short frames");
+	ET_SYSCTL_STAT_ADD64(ctx, children, "oversize",
+	    &stats->rx_oversize, "Oversized frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "fragments",
+	    &stats->rx_fragments, "Fragmented frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "jabbers",
+	    &stats->rx_jabbers, "Frames with jabber error");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "drop",
+	    &stats->rx_drop, "Dropped frames");
+
+	/* TX statistics. */
+	tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "tx", CTLFLAG_RD,
+	    NULL, "TX MAC statistics");
+	children = SYSCTL_CHILDREN(tree);
+	ET_SYSCTL_STAT_ADD64(ctx, children, "bytes",
+	    &stats->tx_bytes, "Good bytes");
+	ET_SYSCTL_STAT_ADD64(ctx, children, "frames",
+	    &stats->tx_frames, "Good frames");
+	ET_SYSCTL_STAT_ADD64(ctx, children, "mcast_frames",
+	    &stats->tx_mcast, "Multicast frames");
+	ET_SYSCTL_STAT_ADD64(ctx, children, "bcast_frames",
+	    &stats->tx_bcast, "Broadcast frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "pause",
+	    &stats->tx_pause, "Pause frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "deferred",
+	    &stats->tx_deferred, "Deferred frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "excess_deferred",
+	    &stats->tx_excess_deferred, "Excessively deferred frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "single_colls",
+	    &stats->tx_single_colls, "Single collisions");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "multi_colls",
+	    &stats->tx_multi_colls, "Multiple collisions");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "late_colls",
+	    &stats->tx_late_colls, "Late collisions");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "excess_colls",
+	    &stats->tx_excess_colls, "Excess collisions");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "total_colls",
+	    &stats->tx_total_colls, "Total collisions");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "pause_honored",
+	    &stats->tx_pause_honored, "Honored pause frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "drop",
+	    &stats->tx_drop, "Dropped frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "jabbers",
+	    &stats->tx_jabbers, "Frames with jabber errors");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "crc_errs",
+	    &stats->tx_crcerrs, "Frames with CRC errors");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "control",
+	    &stats->tx_control, "Control frames");
+	ET_SYSCTL_STAT_ADD64(ctx, children, "oversize",
+	    &stats->tx_oversize, "Oversized frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "undersize",
+	    &stats->tx_undersize, "Undersized frames");
+	ET_SYSCTL_STAT_ADD32(ctx, children, "fragments",
+	    &stats->tx_fragments, "Fragmented frames");
 }
 
+#undef	ET_SYSCTL_STAT_ADD32
+#undef	ET_SYSCTL_STAT_ADD64
+
 static int
 et_sysctl_rx_intr_npkts(SYSCTL_HANDLER_ARGS)
 {
@@ -2446,6 +2561,73 @@ back:
 	return (error);
 }
 
+static void
+et_stats_update(struct et_softc *sc)
+{
+	struct ifnet *ifp;
+	struct et_hw_stats *stats;
+
+	stats = &sc->sc_stats;
+	stats->pkts_64 += CSR_READ_4(sc, ET_STAT_PKTS_64);
+	stats->pkts_65 += CSR_READ_4(sc, ET_STAT_PKTS_65_127);
+	stats->pkts_128 += CSR_READ_4(sc, ET_STAT_PKTS_128_255);
+	stats->pkts_256 += CSR_READ_4(sc, ET_STAT_PKTS_256_511);
+	stats->pkts_512 += CSR_READ_4(sc, ET_STAT_PKTS_512_1023);
+	stats->pkts_1024 += CSR_READ_4(sc, ET_STAT_PKTS_1024_1518);
+	stats->pkts_1519 += CSR_READ_4(sc, ET_STAT_PKTS_1519_1522);
+
+	stats->rx_bytes += CSR_READ_4(sc, ET_STAT_RX_BYTES);
+	stats->rx_frames += CSR_READ_4(sc, ET_STAT_RX_FRAMES);
+	stats->rx_crcerrs += CSR_READ_4(sc, ET_STAT_RX_CRC_ERR);
+	stats->rx_mcast += CSR_READ_4(sc, ET_STAT_RX_MCAST);
+	stats->rx_bcast += CSR_READ_4(sc, ET_STAT_RX_BCAST);
+	stats->rx_control += CSR_READ_4(sc, ET_STAT_RX_CTL);
+	stats->rx_pause += CSR_READ_4(sc, ET_STAT_RX_PAUSE);
+	stats->rx_unknown_control += CSR_READ_4(sc, ET_STAT_RX_UNKNOWN_CTL);
+	stats->rx_alignerrs += CSR_READ_4(sc, ET_STAT_RX_ALIGN_ERR);
+	stats->rx_lenerrs += CSR_READ_4(sc, ET_STAT_RX_LEN_ERR);
+	stats->rx_codeerrs += CSR_READ_4(sc, ET_STAT_RX_CODE_ERR);
+	stats->rx_cserrs += CSR_READ_4(sc, ET_STAT_RX_CS_ERR);
+	stats->rx_runts += CSR_READ_4(sc, ET_STAT_RX_RUNT);
+	stats->rx_oversize += CSR_READ_4(sc, ET_STAT_RX_OVERSIZE);
+	stats->rx_fragments += CSR_READ_4(sc, ET_STAT_RX_FRAG);
+	stats->rx_jabbers += CSR_READ_4(sc, ET_STAT_RX_JABBER);
+	stats->rx_drop += CSR_READ_4(sc, ET_STAT_RX_DROP);
+
+	stats->tx_bytes += CSR_READ_4(sc, ET_STAT_TX_BYTES);
+	stats->tx_frames += CSR_READ_4(sc, ET_STAT_TX_FRAMES);
+	stats->tx_mcast += CSR_READ_4(sc, ET_STAT_TX_MCAST);
+	stats->tx_bcast += CSR_READ_4(sc, ET_STAT_TX_BCAST);
+	stats->tx_pause += CSR_READ_4(sc, ET_STAT_TX_PAUSE);
+	stats->tx_deferred += CSR_READ_4(sc, ET_STAT_TX_DEFER);
+	stats->tx_excess_deferred += CSR_READ_4(sc, ET_STAT_TX_EXCESS_DEFER);
+	stats->tx_single_colls += CSR_READ_4(sc, ET_STAT_TX_SINGLE_COL);
+	stats->tx_multi_colls += CSR_READ_4(sc, ET_STAT_TX_MULTI_COL);
+	stats->tx_late_colls += CSR_READ_4(sc, ET_STAT_TX_LATE_COL);
+	stats->tx_excess_colls += CSR_READ_4(sc, ET_STAT_TX_EXCESS_COL);
+	stats->tx_total_colls += CSR_READ_4(sc, ET_STAT_TX_TOTAL_COL);
+	stats->tx_pause_honored += CSR_READ_4(sc, ET_STAT_TX_PAUSE_HONOR);
+	stats->tx_drop += CSR_READ_4(sc, ET_STAT_TX_DROP);
+	stats->tx_jabbers += CSR_READ_4(sc, ET_STAT_TX_JABBER);
+	stats->tx_crcerrs += CSR_READ_4(sc, ET_STAT_TX_CRC_ERR);
+	stats->tx_control += CSR_READ_4(sc, ET_STAT_TX_CTL);
+	stats->tx_oversize += CSR_READ_4(sc, ET_STAT_TX_OVERSIZE);
+	stats->tx_undersize += CSR_READ_4(sc, ET_STAT_TX_UNDERSIZE);
+	stats->tx_fragments += CSR_READ_4(sc, ET_STAT_TX_FRAG);
+
+	/* Update ifnet counters. */
+	ifp = sc->ifp;
+	ifp->if_opackets = (u_long)stats->tx_frames;
+	ifp->if_collisions = stats->tx_total_colls;
+	ifp->if_oerrors = stats->tx_drop + stats->tx_jabbers +
+	    stats->tx_crcerrs + stats->tx_excess_deferred +
+	    stats->tx_late_colls;
+	ifp->if_ipackets = (u_long)stats->rx_frames;
+	ifp->if_ierrors = stats->rx_crcerrs + stats->rx_alignerrs +
+	    stats->rx_lenerrs + stats->rx_codeerrs + stats->rx_cserrs +
+	    stats->rx_runts + stats->rx_jabbers + stats->rx_drop;
+}
+
 static int
 et_suspend(device_t dev)
 {

Modified: head/sys/dev/et/if_etreg.h
==============================================================================
--- head/sys/dev/et/if_etreg.h	Wed Dec  7 21:29:51 2011	(r228331)
+++ head/sys/dev/et/if_etreg.h	Wed Dec  7 21:46:09 2011	(r228332)
@@ -318,6 +318,52 @@
 #define ET_MAC_ADDR1			0x5040
 #define ET_MAC_ADDR2			0x5044
 
+/* MAC statistics counters. */
+#define	ET_STAT_PKTS_64			0x6080
+#define	ET_STAT_PKTS_65_127		0x6084
+#define	ET_STAT_PKTS_128_255		0x6088
+#define	ET_STAT_PKTS_256_511		0x608C
+#define	ET_STAT_PKTS_512_1023		0x6090
+#define	ET_STAT_PKTS_1024_1518		0x6094
+#define	ET_STAT_PKTS_1519_1522		0x6098
+#define	ET_STAT_RX_BYTES		0x609C
+#define	ET_STAT_RX_FRAMES		0x60A0
+#define	ET_STAT_RX_CRC_ERR		0x60A4
+#define	ET_STAT_RX_MCAST		0x60A8
+#define	ET_STAT_RX_BCAST		0x60AC
+#define	ET_STAT_RX_CTL			0x60B0
+#define	ET_STAT_RX_PAUSE		0x60B4
+#define	ET_STAT_RX_UNKNOWN_CTL		0x60B8
+#define	ET_STAT_RX_ALIGN_ERR		0x60BC
+#define	ET_STAT_RX_LEN_ERR		0x60C0
+#define	ET_STAT_RX_CODE_ERR		0x60C4
+#define	ET_STAT_RX_CS_ERR		0x60C8
+#define	ET_STAT_RX_RUNT			0x60CC
+#define	ET_STAT_RX_OVERSIZE		0x60D0
+#define	ET_STAT_RX_FRAG			0x60D4
+#define	ET_STAT_RX_JABBER		0x60D8
+#define	ET_STAT_RX_DROP			0x60DC
+#define	ET_STAT_TX_BYTES		0x60E0
+#define	ET_STAT_TX_FRAMES		0x60E4
+#define	ET_STAT_TX_MCAST		0x60E8
+#define	ET_STAT_TX_BCAST		0x60EC
+#define	ET_STAT_TX_PAUSE		0x60F0
+#define	ET_STAT_TX_DEFER		0x60F4
+#define	ET_STAT_TX_EXCESS_DEFER		0x60F8
+#define	ET_STAT_TX_SINGLE_COL		0x60FC
+#define	ET_STAT_TX_MULTI_COL		0x6100
+#define	ET_STAT_TX_LATE_COL		0x6104
+#define	ET_STAT_TX_EXCESS_COL		0x6108
+#define	ET_STAT_TX_TOTAL_COL		0x610C
+#define	ET_STAT_TX_PAUSE_HONOR		0x6110
+#define	ET_STAT_TX_DROP			0x6114
+#define	ET_STAT_TX_JABBER		0x6118
+#define	ET_STAT_TX_CRC_ERR		0x611C
+#define	ET_STAT_TX_CTL			0x6120
+#define	ET_STAT_TX_OVERSIZE		0x6124
+#define	ET_STAT_TX_UNDERSIZE		0x6128
+#define	ET_STAT_TX_FRAG			0x612C
+
 #define ET_MMC_CTRL			0x7000
 #define ET_MMC_CTRL_ENABLE		0x00000001
 #define ET_MMC_CTRL_ARB_DISABLE		0x00000002

Modified: head/sys/dev/et/if_etvar.h
==============================================================================
--- head/sys/dev/et/if_etvar.h	Wed Dec  7 21:29:51 2011	(r228331)
+++ head/sys/dev/et/if_etvar.h	Wed Dec  7 21:46:09 2011	(r228332)
@@ -231,6 +231,56 @@ struct et_rxbuf_data {
 	void			(*rbd_discard)(struct et_rxbuf_data *, int);
 };
 
+struct et_hw_stats {
+	/* RX/TX stats. */
+	uint64_t		pkts_64;
+	uint64_t		pkts_65;
+	uint64_t		pkts_128;
+	uint64_t		pkts_256;
+	uint64_t		pkts_512;
+	uint64_t		pkts_1024;
+	uint64_t		pkts_1519;
+	/* RX stats. */
+	uint64_t		rx_bytes;
+	uint64_t		rx_frames;
+	uint32_t		rx_crcerrs;
+	uint64_t		rx_mcast;
+	uint64_t		rx_bcast;
+	uint32_t		rx_control;
+	uint32_t		rx_pause;
+	uint32_t		rx_unknown_control;
+	uint32_t		rx_alignerrs;
+	uint32_t		rx_lenerrs;
+	uint32_t		rx_codeerrs;
+	uint32_t		rx_cserrs;
+	uint32_t		rx_runts;
+	uint64_t		rx_oversize;
+	uint32_t		rx_fragments;
+	uint32_t		rx_jabbers;
+	uint32_t		rx_drop;
+	/* TX stats. */
+	uint64_t		tx_bytes;
+	uint64_t		tx_frames;
+	uint64_t		tx_mcast;
+	uint64_t		tx_bcast;
+	uint32_t		tx_pause;
+	uint32_t		tx_deferred;
+	uint32_t		tx_excess_deferred;
+	uint32_t		tx_single_colls;
+	uint32_t		tx_multi_colls;
+	uint32_t		tx_late_colls;
+	uint32_t		tx_excess_colls;
+	uint32_t		tx_total_colls;
+	uint32_t		tx_pause_honored;
+	uint32_t		tx_drop;
+	uint32_t		tx_jabbers;
+	uint32_t		tx_crcerrs;
+	uint32_t		tx_control;
+	uint64_t		tx_oversize;
+	uint32_t		tx_undersize;
+	uint32_t		tx_fragments;
+};
+
 struct et_softc {
 	struct ifnet		*ifp;
 	device_t		dev;
@@ -271,6 +321,7 @@ struct et_softc {
 	struct et_rxbuf_data	sc_rx_data[ET_RX_NRING];
 	struct et_txbuf_data	sc_tx_data;
 
+	struct et_hw_stats	sc_stats;
 	uint32_t		sc_tx;
 	uint32_t		sc_tx_intr;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201112072146.pB7Lk9L8057126>