Add HW MAC counter support for newer JMC250/JMC260 revisions.
This commit is contained in:
parent
f37739d7ab
commit
450ab47230
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user