Commit ab3f97a9 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller
Browse files

net: mscc: ocelot: export ethtool MAC Merge stats for Felix VSC9959



The Felix VSC9959 switch supports frame preemption and has a MAC Merge
layer. In addition to the structured stats that exist for the eMAC,
export the counters associated with its pMAC (pause, RMON, MAC, PHY,
control) plus the high-level MAC Merge layer stats. The unstructured
ethtool counters, as well as the rtnl_link_stats64 were left to report
only the eMAC counters.

Because statistics processing is quite self-contained in ocelot_stats.c
now, I've opted for introducing an ocelot->mm_supported bool, based on
which the common switch lib does everything, rather than pushing the
TSN-specific code in felix_vsc9959.c, as happens for other TSN stuff.

Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 497eea9f
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -2024,6 +2024,14 @@ static int felix_port_del_dscp_prio(struct dsa_switch *ds, int port, u8 dscp,
	return ocelot_port_del_dscp_prio(ocelot, port, dscp, prio);
}

static void felix_get_mm_stats(struct dsa_switch *ds, int port,
			       struct ethtool_mm_stats *stats)
{
	struct ocelot *ocelot = ds->priv;

	ocelot_port_get_mm_stats(ocelot, port, stats);
}

const struct dsa_switch_ops felix_switch_ops = {
	.get_tag_protocol		= felix_get_tag_protocol,
	.change_tag_protocol		= felix_change_tag_protocol,
@@ -2031,6 +2039,7 @@ const struct dsa_switch_ops felix_switch_ops = {
	.setup				= felix_setup,
	.teardown			= felix_teardown,
	.set_ageing_time		= felix_set_ageing_time,
	.get_mm_stats			= felix_get_mm_stats,
	.get_stats64			= felix_get_stats64,
	.get_pause_stats		= felix_get_pause_stats,
	.get_rmon_stats			= felix_get_rmon_stats,
+38 −0
Original line number Diff line number Diff line
@@ -318,6 +318,29 @@ static const u32 vsc9959_sys_regmap[] = {
	REG(SYS_COUNT_RX_GREEN_PRIO_5,		0x0000a4),
	REG(SYS_COUNT_RX_GREEN_PRIO_6,		0x0000a8),
	REG(SYS_COUNT_RX_GREEN_PRIO_7,		0x0000ac),
	REG(SYS_COUNT_RX_ASSEMBLY_ERRS,		0x0000b0),
	REG(SYS_COUNT_RX_SMD_ERRS,		0x0000b4),
	REG(SYS_COUNT_RX_ASSEMBLY_OK,		0x0000b8),
	REG(SYS_COUNT_RX_MERGE_FRAGMENTS,	0x0000bc),
	REG(SYS_COUNT_RX_PMAC_OCTETS,		0x0000c0),
	REG(SYS_COUNT_RX_PMAC_UNICAST,		0x0000c4),
	REG(SYS_COUNT_RX_PMAC_MULTICAST,	0x0000c8),
	REG(SYS_COUNT_RX_PMAC_BROADCAST,	0x0000cc),
	REG(SYS_COUNT_RX_PMAC_SHORTS,		0x0000d0),
	REG(SYS_COUNT_RX_PMAC_FRAGMENTS,	0x0000d4),
	REG(SYS_COUNT_RX_PMAC_JABBERS,		0x0000d8),
	REG(SYS_COUNT_RX_PMAC_CRC_ALIGN_ERRS,	0x0000dc),
	REG(SYS_COUNT_RX_PMAC_SYM_ERRS,		0x0000e0),
	REG(SYS_COUNT_RX_PMAC_64,		0x0000e4),
	REG(SYS_COUNT_RX_PMAC_65_127,		0x0000e8),
	REG(SYS_COUNT_RX_PMAC_128_255,		0x0000ec),
	REG(SYS_COUNT_RX_PMAC_256_511,		0x0000f0),
	REG(SYS_COUNT_RX_PMAC_512_1023,		0x0000f4),
	REG(SYS_COUNT_RX_PMAC_1024_1526,	0x0000f8),
	REG(SYS_COUNT_RX_PMAC_1527_MAX,		0x0000fc),
	REG(SYS_COUNT_RX_PMAC_PAUSE,		0x000100),
	REG(SYS_COUNT_RX_PMAC_CONTROL,		0x000104),
	REG(SYS_COUNT_RX_PMAC_LONGS,		0x000108),
	REG(SYS_COUNT_TX_OCTETS,		0x000200),
	REG(SYS_COUNT_TX_UNICAST,		0x000204),
	REG(SYS_COUNT_TX_MULTICAST,		0x000208),
@@ -349,6 +372,20 @@ static const u32 vsc9959_sys_regmap[] = {
	REG(SYS_COUNT_TX_GREEN_PRIO_6,		0x000270),
	REG(SYS_COUNT_TX_GREEN_PRIO_7,		0x000274),
	REG(SYS_COUNT_TX_AGED,			0x000278),
	REG(SYS_COUNT_TX_MM_HOLD,		0x00027c),
	REG(SYS_COUNT_TX_MERGE_FRAGMENTS,	0x000280),
	REG(SYS_COUNT_TX_PMAC_OCTETS,		0x000284),
	REG(SYS_COUNT_TX_PMAC_UNICAST,		0x000288),
	REG(SYS_COUNT_TX_PMAC_MULTICAST,	0x00028c),
	REG(SYS_COUNT_TX_PMAC_BROADCAST,	0x000290),
	REG(SYS_COUNT_TX_PMAC_PAUSE,		0x000294),
	REG(SYS_COUNT_TX_PMAC_64,		0x000298),
	REG(SYS_COUNT_TX_PMAC_65_127,		0x00029c),
	REG(SYS_COUNT_TX_PMAC_128_255,		0x0002a0),
	REG(SYS_COUNT_TX_PMAC_256_511,		0x0002a4),
	REG(SYS_COUNT_TX_PMAC_512_1023,		0x0002a8),
	REG(SYS_COUNT_TX_PMAC_1024_1526,	0x0002ac),
	REG(SYS_COUNT_TX_PMAC_1527_MAX,		0x0002b0),
	REG(SYS_COUNT_DROP_LOCAL,		0x000400),
	REG(SYS_COUNT_DROP_TAIL,		0x000404),
	REG(SYS_COUNT_DROP_YELLOW_PRIO_0,	0x000408),
@@ -2623,6 +2660,7 @@ static int felix_pci_probe(struct pci_dev *pdev,
	}

	ocelot->ptp = 1;
	ocelot->mm_supported = true;

	ds = kzalloc(sizeof(struct dsa_switch), GFP_KERNEL);
	if (!ds) {
+279 −10
Original line number Diff line number Diff line
@@ -54,6 +54,29 @@ enum ocelot_stat {
	OCELOT_STAT_RX_GREEN_PRIO_5,
	OCELOT_STAT_RX_GREEN_PRIO_6,
	OCELOT_STAT_RX_GREEN_PRIO_7,
	OCELOT_STAT_RX_ASSEMBLY_ERRS,
	OCELOT_STAT_RX_SMD_ERRS,
	OCELOT_STAT_RX_ASSEMBLY_OK,
	OCELOT_STAT_RX_MERGE_FRAGMENTS,
	OCELOT_STAT_RX_PMAC_OCTETS,
	OCELOT_STAT_RX_PMAC_UNICAST,
	OCELOT_STAT_RX_PMAC_MULTICAST,
	OCELOT_STAT_RX_PMAC_BROADCAST,
	OCELOT_STAT_RX_PMAC_SHORTS,
	OCELOT_STAT_RX_PMAC_FRAGMENTS,
	OCELOT_STAT_RX_PMAC_JABBERS,
	OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS,
	OCELOT_STAT_RX_PMAC_SYM_ERRS,
	OCELOT_STAT_RX_PMAC_64,
	OCELOT_STAT_RX_PMAC_65_127,
	OCELOT_STAT_RX_PMAC_128_255,
	OCELOT_STAT_RX_PMAC_256_511,
	OCELOT_STAT_RX_PMAC_512_1023,
	OCELOT_STAT_RX_PMAC_1024_1526,
	OCELOT_STAT_RX_PMAC_1527_MAX,
	OCELOT_STAT_RX_PMAC_PAUSE,
	OCELOT_STAT_RX_PMAC_CONTROL,
	OCELOT_STAT_RX_PMAC_LONGS,
	OCELOT_STAT_TX_OCTETS,
	OCELOT_STAT_TX_UNICAST,
	OCELOT_STAT_TX_MULTICAST,
@@ -85,6 +108,20 @@ enum ocelot_stat {
	OCELOT_STAT_TX_GREEN_PRIO_6,
	OCELOT_STAT_TX_GREEN_PRIO_7,
	OCELOT_STAT_TX_AGED,
	OCELOT_STAT_TX_MM_HOLD,
	OCELOT_STAT_TX_MERGE_FRAGMENTS,
	OCELOT_STAT_TX_PMAC_OCTETS,
	OCELOT_STAT_TX_PMAC_UNICAST,
	OCELOT_STAT_TX_PMAC_MULTICAST,
	OCELOT_STAT_TX_PMAC_BROADCAST,
	OCELOT_STAT_TX_PMAC_PAUSE,
	OCELOT_STAT_TX_PMAC_64,
	OCELOT_STAT_TX_PMAC_65_127,
	OCELOT_STAT_TX_PMAC_128_255,
	OCELOT_STAT_TX_PMAC_256_511,
	OCELOT_STAT_TX_PMAC_512_1023,
	OCELOT_STAT_TX_PMAC_1024_1526,
	OCELOT_STAT_TX_PMAC_1527_MAX,
	OCELOT_STAT_DROP_LOCAL,
	OCELOT_STAT_DROP_TAIL,
	OCELOT_STAT_DROP_YELLOW_PRIO_0,
@@ -228,9 +265,52 @@ static const struct ocelot_stat_layout ocelot_stats_layout[OCELOT_NUM_STATS] = {
	OCELOT_COMMON_STATS,
};

static const struct ocelot_stat_layout ocelot_mm_stats_layout[OCELOT_NUM_STATS] = {
	OCELOT_COMMON_STATS,
	OCELOT_STAT(RX_ASSEMBLY_ERRS),
	OCELOT_STAT(RX_SMD_ERRS),
	OCELOT_STAT(RX_ASSEMBLY_OK),
	OCELOT_STAT(RX_MERGE_FRAGMENTS),
	OCELOT_STAT(TX_MERGE_FRAGMENTS),
	OCELOT_STAT(RX_PMAC_OCTETS),
	OCELOT_STAT(RX_PMAC_UNICAST),
	OCELOT_STAT(RX_PMAC_MULTICAST),
	OCELOT_STAT(RX_PMAC_BROADCAST),
	OCELOT_STAT(RX_PMAC_SHORTS),
	OCELOT_STAT(RX_PMAC_FRAGMENTS),
	OCELOT_STAT(RX_PMAC_JABBERS),
	OCELOT_STAT(RX_PMAC_CRC_ALIGN_ERRS),
	OCELOT_STAT(RX_PMAC_SYM_ERRS),
	OCELOT_STAT(RX_PMAC_64),
	OCELOT_STAT(RX_PMAC_65_127),
	OCELOT_STAT(RX_PMAC_128_255),
	OCELOT_STAT(RX_PMAC_256_511),
	OCELOT_STAT(RX_PMAC_512_1023),
	OCELOT_STAT(RX_PMAC_1024_1526),
	OCELOT_STAT(RX_PMAC_1527_MAX),
	OCELOT_STAT(RX_PMAC_PAUSE),
	OCELOT_STAT(RX_PMAC_CONTROL),
	OCELOT_STAT(RX_PMAC_LONGS),
	OCELOT_STAT(TX_PMAC_OCTETS),
	OCELOT_STAT(TX_PMAC_UNICAST),
	OCELOT_STAT(TX_PMAC_MULTICAST),
	OCELOT_STAT(TX_PMAC_BROADCAST),
	OCELOT_STAT(TX_PMAC_PAUSE),
	OCELOT_STAT(TX_PMAC_64),
	OCELOT_STAT(TX_PMAC_65_127),
	OCELOT_STAT(TX_PMAC_128_255),
	OCELOT_STAT(TX_PMAC_256_511),
	OCELOT_STAT(TX_PMAC_512_1023),
	OCELOT_STAT(TX_PMAC_1024_1526),
	OCELOT_STAT(TX_PMAC_1527_MAX),
};

static const struct ocelot_stat_layout *
ocelot_get_stats_layout(struct ocelot *ocelot)
{
	if (ocelot->mm_supported)
		return ocelot_mm_stats_layout;

	return ocelot_stats_layout;
}

@@ -410,14 +490,63 @@ static void ocelot_port_pause_stats_cb(struct ocelot *ocelot, int port, void *pr
	pause_stats->rx_pause_frames = s[OCELOT_STAT_RX_PAUSE];
}

static void ocelot_port_pmac_pause_stats_cb(struct ocelot *ocelot, int port,
					    void *priv)
{
	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
	struct ethtool_pause_stats *pause_stats = priv;

	pause_stats->tx_pause_frames = s[OCELOT_STAT_TX_PMAC_PAUSE];
	pause_stats->rx_pause_frames = s[OCELOT_STAT_RX_PMAC_PAUSE];
}

static void ocelot_port_mm_stats_cb(struct ocelot *ocelot, int port,
				    void *priv)
{
	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
	struct ethtool_mm_stats *stats = priv;

	stats->MACMergeFrameAssErrorCount = s[OCELOT_STAT_RX_ASSEMBLY_ERRS];
	stats->MACMergeFrameSmdErrorCount = s[OCELOT_STAT_RX_SMD_ERRS];
	stats->MACMergeFrameAssOkCount = s[OCELOT_STAT_RX_ASSEMBLY_OK];
	stats->MACMergeFragCountRx = s[OCELOT_STAT_RX_MERGE_FRAGMENTS];
	stats->MACMergeFragCountTx = s[OCELOT_STAT_TX_MERGE_FRAGMENTS];
	stats->MACMergeHoldCount = s[OCELOT_STAT_TX_MM_HOLD];
}

void ocelot_port_get_pause_stats(struct ocelot *ocelot, int port,
				 struct ethtool_pause_stats *pause_stats)
{
	struct net_device *dev;

	switch (pause_stats->src) {
	case ETHTOOL_MAC_STATS_SRC_EMAC:
		ocelot_port_stats_run(ocelot, port, pause_stats,
				      ocelot_port_pause_stats_cb);
		break;
	case ETHTOOL_MAC_STATS_SRC_PMAC:
		if (ocelot->mm_supported)
			ocelot_port_stats_run(ocelot, port, pause_stats,
					      ocelot_port_pmac_pause_stats_cb);
		break;
	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
		dev = ocelot->ops->port_to_netdev(ocelot, port);
		ethtool_aggregate_pause_stats(dev, pause_stats);
		break;
	}
}
EXPORT_SYMBOL_GPL(ocelot_port_get_pause_stats);

void ocelot_port_get_mm_stats(struct ocelot *ocelot, int port,
			      struct ethtool_mm_stats *stats)
{
	if (!ocelot->mm_supported)
		return;

	ocelot_port_stats_run(ocelot, port, stats, ocelot_port_mm_stats_cb);
}
EXPORT_SYMBOL_GPL(ocelot_port_get_mm_stats);

static const struct ethtool_rmon_hist_range ocelot_rmon_ranges[] = {
	{   64,    64 },
	{   65,   127 },
@@ -456,14 +585,57 @@ static void ocelot_port_rmon_stats_cb(struct ocelot *ocelot, int port, void *pri
	rmon_stats->hist_tx[6] = s[OCELOT_STAT_TX_1024_1526];
}

static void ocelot_port_pmac_rmon_stats_cb(struct ocelot *ocelot, int port,
					   void *priv)
{
	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
	struct ethtool_rmon_stats *rmon_stats = priv;

	rmon_stats->undersize_pkts = s[OCELOT_STAT_RX_PMAC_SHORTS];
	rmon_stats->oversize_pkts = s[OCELOT_STAT_RX_PMAC_LONGS];
	rmon_stats->fragments = s[OCELOT_STAT_RX_PMAC_FRAGMENTS];
	rmon_stats->jabbers = s[OCELOT_STAT_RX_PMAC_JABBERS];

	rmon_stats->hist[0] = s[OCELOT_STAT_RX_PMAC_64];
	rmon_stats->hist[1] = s[OCELOT_STAT_RX_PMAC_65_127];
	rmon_stats->hist[2] = s[OCELOT_STAT_RX_PMAC_128_255];
	rmon_stats->hist[3] = s[OCELOT_STAT_RX_PMAC_256_511];
	rmon_stats->hist[4] = s[OCELOT_STAT_RX_PMAC_512_1023];
	rmon_stats->hist[5] = s[OCELOT_STAT_RX_PMAC_1024_1526];
	rmon_stats->hist[6] = s[OCELOT_STAT_RX_PMAC_1527_MAX];

	rmon_stats->hist_tx[0] = s[OCELOT_STAT_TX_PMAC_64];
	rmon_stats->hist_tx[1] = s[OCELOT_STAT_TX_PMAC_65_127];
	rmon_stats->hist_tx[2] = s[OCELOT_STAT_TX_PMAC_128_255];
	rmon_stats->hist_tx[3] = s[OCELOT_STAT_TX_PMAC_128_255];
	rmon_stats->hist_tx[4] = s[OCELOT_STAT_TX_PMAC_256_511];
	rmon_stats->hist_tx[5] = s[OCELOT_STAT_TX_PMAC_512_1023];
	rmon_stats->hist_tx[6] = s[OCELOT_STAT_TX_PMAC_1024_1526];
}

void ocelot_port_get_rmon_stats(struct ocelot *ocelot, int port,
				struct ethtool_rmon_stats *rmon_stats,
				const struct ethtool_rmon_hist_range **ranges)
{
	struct net_device *dev;

	*ranges = ocelot_rmon_ranges;

	switch (rmon_stats->src) {
	case ETHTOOL_MAC_STATS_SRC_EMAC:
		ocelot_port_stats_run(ocelot, port, rmon_stats,
				      ocelot_port_rmon_stats_cb);
		break;
	case ETHTOOL_MAC_STATS_SRC_PMAC:
		if (ocelot->mm_supported)
			ocelot_port_stats_run(ocelot, port, rmon_stats,
					      ocelot_port_pmac_rmon_stats_cb);
		break;
	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
		dev = ocelot->ops->port_to_netdev(ocelot, port);
		ethtool_aggregate_rmon_stats(dev, rmon_stats);
		break;
	}
}
EXPORT_SYMBOL_GPL(ocelot_port_get_rmon_stats);

@@ -475,11 +647,35 @@ static void ocelot_port_ctrl_stats_cb(struct ocelot *ocelot, int port, void *pri
	ctrl_stats->MACControlFramesReceived = s[OCELOT_STAT_RX_CONTROL];
}

static void ocelot_port_pmac_ctrl_stats_cb(struct ocelot *ocelot, int port,
					   void *priv)
{
	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
	struct ethtool_eth_ctrl_stats *ctrl_stats = priv;

	ctrl_stats->MACControlFramesReceived = s[OCELOT_STAT_RX_PMAC_CONTROL];
}

void ocelot_port_get_eth_ctrl_stats(struct ocelot *ocelot, int port,
				    struct ethtool_eth_ctrl_stats *ctrl_stats)
{
	struct net_device *dev;

	switch (ctrl_stats->src) {
	case ETHTOOL_MAC_STATS_SRC_EMAC:
		ocelot_port_stats_run(ocelot, port, ctrl_stats,
				      ocelot_port_ctrl_stats_cb);
		break;
	case ETHTOOL_MAC_STATS_SRC_PMAC:
		if (ocelot->mm_supported)
			ocelot_port_stats_run(ocelot, port, ctrl_stats,
					      ocelot_port_pmac_ctrl_stats_cb);
		break;
	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
		dev = ocelot->ops->port_to_netdev(ocelot, port);
		ethtool_aggregate_ctrl_stats(dev, ctrl_stats);
		break;
	}
}
EXPORT_SYMBOL_GPL(ocelot_port_get_eth_ctrl_stats);

@@ -525,11 +721,60 @@ static void ocelot_port_mac_stats_cb(struct ocelot *ocelot, int port, void *priv
	mac_stats->AlignmentErrors = s[OCELOT_STAT_RX_CRC_ALIGN_ERRS];
}

static void ocelot_port_pmac_mac_stats_cb(struct ocelot *ocelot, int port,
					  void *priv)
{
	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
	struct ethtool_eth_mac_stats *mac_stats = priv;

	mac_stats->OctetsTransmittedOK = s[OCELOT_STAT_TX_PMAC_OCTETS];
	mac_stats->FramesTransmittedOK = s[OCELOT_STAT_TX_PMAC_64] +
					 s[OCELOT_STAT_TX_PMAC_65_127] +
					 s[OCELOT_STAT_TX_PMAC_128_255] +
					 s[OCELOT_STAT_TX_PMAC_256_511] +
					 s[OCELOT_STAT_TX_PMAC_512_1023] +
					 s[OCELOT_STAT_TX_PMAC_1024_1526] +
					 s[OCELOT_STAT_TX_PMAC_1527_MAX];
	mac_stats->OctetsReceivedOK = s[OCELOT_STAT_RX_PMAC_OCTETS];
	mac_stats->FramesReceivedOK = s[OCELOT_STAT_RX_PMAC_64] +
				      s[OCELOT_STAT_RX_PMAC_65_127] +
				      s[OCELOT_STAT_RX_PMAC_128_255] +
				      s[OCELOT_STAT_RX_PMAC_256_511] +
				      s[OCELOT_STAT_RX_PMAC_512_1023] +
				      s[OCELOT_STAT_RX_PMAC_1024_1526] +
				      s[OCELOT_STAT_RX_PMAC_1527_MAX];
	mac_stats->MulticastFramesXmittedOK = s[OCELOT_STAT_TX_PMAC_MULTICAST];
	mac_stats->BroadcastFramesXmittedOK = s[OCELOT_STAT_TX_PMAC_BROADCAST];
	mac_stats->MulticastFramesReceivedOK = s[OCELOT_STAT_RX_PMAC_MULTICAST];
	mac_stats->BroadcastFramesReceivedOK = s[OCELOT_STAT_RX_PMAC_BROADCAST];
	mac_stats->FrameTooLongErrors = s[OCELOT_STAT_RX_PMAC_LONGS];
	/* Sadly, C_RX_CRC is the sum of FCS and alignment errors, they are not
	 * counted individually.
	 */
	mac_stats->FrameCheckSequenceErrors = s[OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS];
	mac_stats->AlignmentErrors = s[OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS];
}

void ocelot_port_get_eth_mac_stats(struct ocelot *ocelot, int port,
				   struct ethtool_eth_mac_stats *mac_stats)
{
	struct net_device *dev;

	switch (mac_stats->src) {
	case ETHTOOL_MAC_STATS_SRC_EMAC:
		ocelot_port_stats_run(ocelot, port, mac_stats,
				      ocelot_port_mac_stats_cb);
		break;
	case ETHTOOL_MAC_STATS_SRC_PMAC:
		if (ocelot->mm_supported)
			ocelot_port_stats_run(ocelot, port, mac_stats,
					      ocelot_port_pmac_mac_stats_cb);
		break;
	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
		dev = ocelot->ops->port_to_netdev(ocelot, port);
		ethtool_aggregate_mac_stats(dev, mac_stats);
		break;
	}
}
EXPORT_SYMBOL_GPL(ocelot_port_get_eth_mac_stats);

@@ -541,11 +786,35 @@ static void ocelot_port_phy_stats_cb(struct ocelot *ocelot, int port, void *priv
	phy_stats->SymbolErrorDuringCarrier = s[OCELOT_STAT_RX_SYM_ERRS];
}

static void ocelot_port_pmac_phy_stats_cb(struct ocelot *ocelot, int port,
					  void *priv)
{
	u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS];
	struct ethtool_eth_phy_stats *phy_stats = priv;

	phy_stats->SymbolErrorDuringCarrier = s[OCELOT_STAT_RX_PMAC_SYM_ERRS];
}

void ocelot_port_get_eth_phy_stats(struct ocelot *ocelot, int port,
				   struct ethtool_eth_phy_stats *phy_stats)
{
	struct net_device *dev;

	switch (phy_stats->src) {
	case ETHTOOL_MAC_STATS_SRC_EMAC:
		ocelot_port_stats_run(ocelot, port, phy_stats,
				      ocelot_port_phy_stats_cb);
		break;
	case ETHTOOL_MAC_STATS_SRC_PMAC:
		if (ocelot->mm_supported)
			ocelot_port_stats_run(ocelot, port, phy_stats,
					      ocelot_port_pmac_phy_stats_cb);
		break;
	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
		dev = ocelot->ops->port_to_netdev(ocelot, port);
		ethtool_aggregate_phy_stats(dev, phy_stats);
		break;
	}
}
EXPORT_SYMBOL_GPL(ocelot_port_get_eth_phy_stats);

+40 −0
Original line number Diff line number Diff line
@@ -362,6 +362,29 @@ enum ocelot_reg {
	SYS_COUNT_RX_GREEN_PRIO_5,
	SYS_COUNT_RX_GREEN_PRIO_6,
	SYS_COUNT_RX_GREEN_PRIO_7,
	SYS_COUNT_RX_ASSEMBLY_ERRS,
	SYS_COUNT_RX_SMD_ERRS,
	SYS_COUNT_RX_ASSEMBLY_OK,
	SYS_COUNT_RX_MERGE_FRAGMENTS,
	SYS_COUNT_RX_PMAC_OCTETS,
	SYS_COUNT_RX_PMAC_UNICAST,
	SYS_COUNT_RX_PMAC_MULTICAST,
	SYS_COUNT_RX_PMAC_BROADCAST,
	SYS_COUNT_RX_PMAC_SHORTS,
	SYS_COUNT_RX_PMAC_FRAGMENTS,
	SYS_COUNT_RX_PMAC_JABBERS,
	SYS_COUNT_RX_PMAC_CRC_ALIGN_ERRS,
	SYS_COUNT_RX_PMAC_SYM_ERRS,
	SYS_COUNT_RX_PMAC_64,
	SYS_COUNT_RX_PMAC_65_127,
	SYS_COUNT_RX_PMAC_128_255,
	SYS_COUNT_RX_PMAC_256_511,
	SYS_COUNT_RX_PMAC_512_1023,
	SYS_COUNT_RX_PMAC_1024_1526,
	SYS_COUNT_RX_PMAC_1527_MAX,
	SYS_COUNT_RX_PMAC_PAUSE,
	SYS_COUNT_RX_PMAC_CONTROL,
	SYS_COUNT_RX_PMAC_LONGS,
	SYS_COUNT_TX_OCTETS,
	SYS_COUNT_TX_UNICAST,
	SYS_COUNT_TX_MULTICAST,
@@ -393,6 +416,20 @@ enum ocelot_reg {
	SYS_COUNT_TX_GREEN_PRIO_6,
	SYS_COUNT_TX_GREEN_PRIO_7,
	SYS_COUNT_TX_AGED,
	SYS_COUNT_TX_MM_HOLD,
	SYS_COUNT_TX_MERGE_FRAGMENTS,
	SYS_COUNT_TX_PMAC_OCTETS,
	SYS_COUNT_TX_PMAC_UNICAST,
	SYS_COUNT_TX_PMAC_MULTICAST,
	SYS_COUNT_TX_PMAC_BROADCAST,
	SYS_COUNT_TX_PMAC_PAUSE,
	SYS_COUNT_TX_PMAC_64,
	SYS_COUNT_TX_PMAC_65_127,
	SYS_COUNT_TX_PMAC_128_255,
	SYS_COUNT_TX_PMAC_256_511,
	SYS_COUNT_TX_PMAC_512_1023,
	SYS_COUNT_TX_PMAC_1024_1526,
	SYS_COUNT_TX_PMAC_1527_MAX,
	SYS_COUNT_DROP_LOCAL,
	SYS_COUNT_DROP_TAIL,
	SYS_COUNT_DROP_YELLOW_PRIO_0,
@@ -814,6 +851,7 @@ struct ocelot {
	struct workqueue_struct		*owq;

	u8				ptp:1;
	u8				mm_supported:1;
	struct ptp_clock		*ptp_clock;
	struct ptp_clock_info		ptp_info;
	struct hwtstamp_config		hwtstamp_config;
@@ -937,6 +975,8 @@ void ocelot_port_get_stats64(struct ocelot *ocelot, int port,
			     struct rtnl_link_stats64 *stats);
void ocelot_port_get_pause_stats(struct ocelot *ocelot, int port,
				 struct ethtool_pause_stats *pause_stats);
void ocelot_port_get_mm_stats(struct ocelot *ocelot, int port,
			      struct ethtool_mm_stats *stats);
void ocelot_port_get_rmon_stats(struct ocelot *ocelot, int port,
				struct ethtool_rmon_stats *rmon_stats,
				const struct ethtool_rmon_hist_range **ranges);