Author: yongari
Date: Thu Dec  4 02:16:53 2008
New Revision: 185597
URL: http://svn.freebsd.org/changeset/base/185597

Log:
  Add HW MAC counter support for newer JMC250/JMC260 revisions.

Modified:
  head/sys/dev/jme/if_jme.c
  head/sys/dev/jme/if_jmereg.h
  head/sys/dev/jme/if_jmevar.h

Modified: head/sys/dev/jme/if_jme.c
==============================================================================
--- head/sys/dev/jme/if_jme.c   Thu Dec  4 01:58:40 2008        (r185596)
+++ head/sys/dev/jme/if_jme.c   Thu Dec  4 02:16:53 2008        (r185597)
@@ -150,6 +150,9 @@ static void jme_init_ssb(struct jme_soft
 static int jme_newbuf(struct jme_softc *, struct jme_rxdesc *);
 static void jme_set_vlan(struct jme_softc *);
 static void jme_set_filter(struct jme_softc *);
+static void jme_stats_clear(struct jme_softc *);
+static void jme_stats_save(struct jme_softc *);
+static void jme_stats_update(struct jme_softc *);
 static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int);
 static int sysctl_hw_jme_tx_coal_to(SYSCTL_HANDLER_ARGS);
 static int sysctl_hw_jme_tx_coal_pkt(SYSCTL_HANDLER_ARGS);
@@ -656,6 +659,7 @@ jme_attach(device_t dev)
                    CHIPMODE_REVFM(sc->jme_chip_rev) == 2)
                        sc->jme_flags |= JME_FLAG_DMA32BIT;
                sc->jme_flags |= JME_FLAG_TXCLK;
+               sc->jme_flags |= JME_FLAG_HWMIB;
        }
 
        /* Reset the ethernet controller. */
@@ -887,35 +891,41 @@ jme_detach(device_t dev)
        return (0);
 }
 
+#define        JME_SYSCTL_STAT_ADD32(c, h, n, p, d)    \
+           SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d)
+
 static void
 jme_sysctl_node(struct jme_softc *sc)
 {
+       struct sysctl_ctx_list *ctx;
+       struct sysctl_oid_list *child, *parent;
+       struct sysctl_oid *tree;
+       struct jme_hw_stats *stats;
        int error;
 
-       SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->jme_dev),
-           SYSCTL_CHILDREN(device_get_sysctl_tree(sc->jme_dev)), OID_AUTO,
-           "tx_coal_to", CTLTYPE_INT | CTLFLAG_RW, &sc->jme_tx_coal_to,
-           0, sysctl_hw_jme_tx_coal_to, "I", "jme tx coalescing timeout");
-
-       SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->jme_dev),
-           SYSCTL_CHILDREN(device_get_sysctl_tree(sc->jme_dev)), OID_AUTO,
-           "tx_coal_pkt", CTLTYPE_INT | CTLFLAG_RW, &sc->jme_tx_coal_pkt,
-           0, sysctl_hw_jme_tx_coal_pkt, "I", "jme tx coalescing packet");
-
-       SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->jme_dev),
-           SYSCTL_CHILDREN(device_get_sysctl_tree(sc->jme_dev)), OID_AUTO,
-           "rx_coal_to", CTLTYPE_INT | CTLFLAG_RW, &sc->jme_rx_coal_to,
-           0, sysctl_hw_jme_rx_coal_to, "I", "jme rx coalescing timeout");
-
-       SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->jme_dev),
-           SYSCTL_CHILDREN(device_get_sysctl_tree(sc->jme_dev)), OID_AUTO,
-           "rx_coal_pkt", CTLTYPE_INT | CTLFLAG_RW, &sc->jme_rx_coal_pkt,
-           0, sysctl_hw_jme_rx_coal_pkt, "I", "jme rx coalescing packet");
-
-       SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->jme_dev),
-           SYSCTL_CHILDREN(device_get_sysctl_tree(sc->jme_dev)), OID_AUTO,
-           "process_limit", CTLTYPE_INT | CTLFLAG_RW, &sc->jme_process_limit,
-           0, sysctl_hw_jme_proc_limit, "I",
+       stats = &sc->jme_stats;
+       ctx = device_get_sysctl_ctx(sc->jme_dev);
+       child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->jme_dev));
+
+       SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_coal_to",
+           CTLTYPE_INT | CTLFLAG_RW, &sc->jme_tx_coal_to, 0,
+           sysctl_hw_jme_tx_coal_to, "I", "jme tx coalescing timeout");
+
+       SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_coal_pkt",
+           CTLTYPE_INT | CTLFLAG_RW, &sc->jme_tx_coal_pkt, 0,
+           sysctl_hw_jme_tx_coal_pkt, "I", "jme tx coalescing packet");
+
+       SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_coal_to",
+           CTLTYPE_INT | CTLFLAG_RW, &sc->jme_rx_coal_to, 0,
+           sysctl_hw_jme_rx_coal_to, "I", "jme rx coalescing timeout");
+
+       SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_coal_pkt",
+           CTLTYPE_INT | CTLFLAG_RW, &sc->jme_rx_coal_pkt, 0,
+           sysctl_hw_jme_rx_coal_pkt, "I", "jme rx coalescing packet");
+
+       SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "process_limit",
+           CTLTYPE_INT | CTLFLAG_RW, &sc->jme_process_limit, 0,
+           sysctl_hw_jme_proc_limit, "I",
            "max number of Rx events to process");
 
        /* Pull in device tunables. */
@@ -984,8 +994,43 @@ jme_sysctl_node(struct jme_softc *sc)
                        sc->jme_rx_coal_pkt = PCCRX_COAL_PKT_DEFAULT;
                }
        }
+
+       if ((sc->jme_flags & JME_FLAG_HWMIB) == 0)
+               return;
+
+       tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD,
+           NULL, "JME 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);
+       JME_SYSCTL_STAT_ADD32(ctx, child, "good_frames",
+           &stats->rx_good_frames, "Good frames");
+       JME_SYSCTL_STAT_ADD32(ctx, child, "crc_errs",
+           &stats->rx_crc_errs, "CRC errors");
+       JME_SYSCTL_STAT_ADD32(ctx, child, "mii_errs",
+           &stats->rx_mii_errs, "MII errors");
+       JME_SYSCTL_STAT_ADD32(ctx, child, "fifo_oflows",
+           &stats->rx_fifo_oflows, "FIFO overflows");
+       JME_SYSCTL_STAT_ADD32(ctx, child, "desc_empty",
+           &stats->rx_desc_empty, "Descriptor empty");
+       JME_SYSCTL_STAT_ADD32(ctx, child, "bad_frames",
+           &stats->rx_bad_frames, "Bad frames");
+
+       /* Tx statistics. */
+       tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "tx", CTLFLAG_RD,
+           NULL, "Tx MAC statistics");
+       child = SYSCTL_CHILDREN(tree);
+       JME_SYSCTL_STAT_ADD32(ctx, child, "good_frames",
+           &stats->tx_good_frames, "Good frames");
+       JME_SYSCTL_STAT_ADD32(ctx, child, "bad_frames",
+           &stats->tx_bad_frames, "Bad frames");
 }
 
+#undef JME_SYSCTL_STAT_ADD32
+
 struct jme_dmamap_arg {
        bus_addr_t      jme_busaddr;
 };
@@ -2164,6 +2209,7 @@ jme_link_task(void *arg, int pending)
        /* Program MAC with resolved speed/duplex/flow-control. */
        if ((sc->jme_flags & JME_FLAG_LINK) != 0) {
                jme_mac_config(sc);
+               jme_stats_clear(sc);
 
                CSR_WRITE_4(sc, JME_RXCSR, sc->jme_rxcsr);
                CSR_WRITE_4(sc, JME_TXCSR, sc->jme_txcsr);
@@ -2553,6 +2599,7 @@ jme_tick(void *arg)
         * faster and limit the maximum delay to a hz.
         */
        jme_txeof(sc);
+       jme_stats_update(sc);
        jme_watchdog(sc);
        callout_reset(&sc->jme_tick_ch, hz, jme_tick, sc);
 }
@@ -2862,6 +2909,8 @@ jme_stop(struct jme_softc *sc)
                        txd->tx_ndesc = 0;
                }
         }
+       jme_stats_update(sc);
+       jme_stats_save(sc);
 }
 
 static void
@@ -3093,6 +3142,76 @@ jme_set_filter(struct jme_softc *sc)
        CSR_WRITE_4(sc, JME_RXMAC, rxcfg);
 }
 
+static void
+jme_stats_clear(struct jme_softc *sc)
+{
+
+       JME_LOCK_ASSERT(sc);
+
+       if ((sc->jme_flags & JME_FLAG_HWMIB) == 0)
+               return;
+
+       /* Disable and clear counters. */
+       CSR_WRITE_4(sc, JME_STATCSR, 0xFFFFFFFF);
+       /* Activate hw counters. */
+       CSR_WRITE_4(sc, JME_STATCSR, 0);
+       CSR_READ_4(sc, JME_STATCSR);
+       bzero(&sc->jme_stats, sizeof(struct jme_hw_stats));
+}
+
+static void
+jme_stats_save(struct jme_softc *sc)
+{
+
+       JME_LOCK_ASSERT(sc);
+
+       if ((sc->jme_flags & JME_FLAG_HWMIB) == 0)
+               return;
+       /* Save current counters. */
+       bcopy(&sc->jme_stats, &sc->jme_ostats, sizeof(struct jme_hw_stats));
+       /* Disable and clear counters. */
+       CSR_WRITE_4(sc, JME_STATCSR, 0xFFFFFFFF);
+}
+
+static void
+jme_stats_update(struct jme_softc *sc)
+{
+       struct jme_hw_stats *stat, *ostat;
+       uint32_t reg;
+
+       JME_LOCK_ASSERT(sc);
+
+       if ((sc->jme_flags & JME_FLAG_HWMIB) == 0)
+               return;
+       stat = &sc->jme_stats;
+       ostat = &sc->jme_ostats;
+       stat->tx_good_frames = CSR_READ_4(sc, JME_STAT_TXGOOD);
+       stat->rx_good_frames = CSR_READ_4(sc, JME_STAT_RXGOOD);
+       reg = CSR_READ_4(sc, JME_STAT_CRCMII);
+       stat->rx_crc_errs = (reg & STAT_RX_CRC_ERR_MASK) >>
+           STAT_RX_CRC_ERR_SHIFT;
+       stat->rx_mii_errs = (reg & STAT_RX_MII_ERR_MASK) >>
+           STAT_RX_MII_ERR_SHIFT;
+       reg = CSR_READ_4(sc, JME_STAT_RXERR);
+       stat->rx_fifo_oflows = (reg & STAT_RXERR_OFLOW_MASK) >>
+           STAT_RXERR_OFLOW_SHIFT;
+       stat->rx_desc_empty = (reg & STAT_RXERR_MPTY_MASK) >>
+           STAT_RXERR_MPTY_SHIFT;
+       reg = CSR_READ_4(sc, JME_STAT_FAIL);
+       stat->rx_bad_frames = (reg & STAT_FAIL_RX_MASK) >> STAT_FAIL_RX_SHIFT;
+       stat->tx_bad_frames = (reg & STAT_FAIL_TX_MASK) >> STAT_FAIL_TX_SHIFT;
+
+       /* Account for previous counters. */
+       stat->rx_good_frames += ostat->rx_good_frames;
+       stat->rx_crc_errs += ostat->rx_crc_errs;
+       stat->rx_mii_errs += ostat->rx_mii_errs;
+       stat->rx_fifo_oflows += ostat->rx_fifo_oflows;
+       stat->rx_desc_empty += ostat->rx_desc_empty;
+       stat->rx_bad_frames += ostat->rx_bad_frames;
+       stat->tx_good_frames += ostat->tx_good_frames;
+       stat->tx_bad_frames += ostat->tx_bad_frames;
+}
+
 static int
 sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high)
 {

Modified: head/sys/dev/jme/if_jmereg.h
==============================================================================
--- head/sys/dev/jme/if_jmereg.h        Thu Dec  4 01:58:40 2008        
(r185596)
+++ head/sys/dev/jme/if_jmereg.h        Thu Dec  4 02:16:53 2008        
(r185597)
@@ -199,6 +199,7 @@
 #define        TXMAC_IFG2_DEFAULT      0x40000000
 #define        TXMAC_IFG1_MASK         0x30000000
 #define        TXMAC_IFG1_DEFAULT      0x20000000
+#define        TXMAC_PAUSE_CNT_MASK    0x00FF0000
 #define        TXMAC_THRESH_1_PKT      0x00000300
 #define        TXMAC_THRESH_1_2_PKT    0x00000200
 #define        TXMAC_THRESH_1_4_PKT    0x00000100
@@ -403,6 +404,44 @@
 #define        PMCS_MAGIC_FRAME_ENB    0x00000001
 #define        PMCS_WOL_ENB_MASK       0x0000FFFF
 
+/*
+ * Statistic registers control and status.
+ * These statistics registers are valid only for JMC250/JMC260 REVFM >= 2.
+ */
+#define        JME_STATCSR             0x0064
+#define        STATCSR_RXMPT_DIS       0x00000080
+#define        STATCSR_OFLOW_DIS       0x00000040
+#define        STATCSR_MIIRXER_DIS     0x00000020
+#define        STATCSR_CRCERR_DIS      0x00000010
+#define        STATCSR_RXBAD_DIS       0x00000008
+#define        STATCSR_RXGOOD_DIS      0x00000004
+#define        STATCSR_TXBAD_DIS       0x00000002
+#define        STATCSR_TXGOOD_DIS      0x00000001
+
+#define        JME_STAT_TXGOOD         0x0068
+
+#define        JME_STAT_RXGOOD         0x006C
+
+#define        JME_STAT_CRCMII         0x0070
+#define        STAT_RX_CRC_ERR_MASK    0xFFFF0000
+#define        STAT_RX_MII_ERR_MASK    0x0000FFFF
+#define        STAT_RX_CRC_ERR_SHIFT   16
+#define        STAT_RX_MII_ERR_SHIFT   0
+
+#define        JME_STAT_RXERR          0x0074
+#define        STAT_RXERR_OFLOW_MASK   0xFFFF0000
+#define        STAT_RXERR_MPTY_MASK    0x0000FFFF
+#define        STAT_RXERR_OFLOW_SHIFT  16
+#define        STAT_RXERR_MPTY_SHIFT   0
+
+#define        JME_STAT_RESERVED1      0x0078
+
+#define        JME_STAT_FAIL           0x007C
+#define        STAT_FAIL_RX_MASK       0xFFFF0000
+#define        STAT_FAIL_TX_MASK       0x0000FFFF
+#define        STAT_FAIL_RX_SHIFT      16
+#define        STAT_FAIL_TX_SHIFT      0
+
 /* Giga PHY & EEPROM registers. */
 #define        JME_PHY_EEPROM_BASE_ADDR        0x0400
 

Modified: head/sys/dev/jme/if_jmevar.h
==============================================================================
--- head/sys/dev/jme/if_jmevar.h        Thu Dec  4 01:58:40 2008        
(r185596)
+++ head/sys/dev/jme/if_jmevar.h        Thu Dec  4 02:16:53 2008        
(r185597)
@@ -154,6 +154,18 @@ struct jme_ring_data {
     (sizeof(struct jme_desc) * JME_RX_RING_CNT)
 #define        JME_SSB_SIZE            sizeof(struct jme_ssb)
 
+/* Statistics counters. */
+struct jme_hw_stats {
+       uint32_t                rx_good_frames;
+       uint32_t                rx_crc_errs;
+       uint32_t                rx_mii_errs;
+       uint32_t                rx_fifo_oflows;
+       uint32_t                rx_desc_empty;
+       uint32_t                rx_bad_frames;
+       uint32_t                tx_good_frames;
+       uint32_t                tx_bad_frames;
+};
+
 /*
  * Software state per device.
  */
@@ -183,9 +195,12 @@ struct jme_softc {
 #define        JME_FLAG_NOJUMBO        0x0080
 #define        JME_FLAG_TXCLK          0x0100
 #define        JME_FLAG_DMA32BIT       0x0200
+#define        JME_FLAG_HWMIB          0x0400
 #define        JME_FLAG_DETACH         0x4000
 #define        JME_FLAG_LINK           0x8000
 
+       struct jme_hw_stats     jme_ostats;
+       struct jme_hw_stats     jme_stats;
        struct callout          jme_tick_ch;
        struct jme_chain_data   jme_cdata;
        struct jme_ring_data    jme_rdata;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to