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

This commit is contained in:
Pyun YongHyeon 2008-12-04 02:16:53 +00:00
parent f37739d7ab
commit 450ab47230
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=185597
3 changed files with 193 additions and 20 deletions

View File

@ -150,6 +150,9 @@ static void jme_init_ssb(struct jme_softc *);
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");
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(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(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(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(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(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(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(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",
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)
{

View File

@ -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

View File

@ -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;