Commit 37a96c20 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Jakub Kicinski
Browse files

net: fman_memac: report structured ethtool counters



The FMan driver has support for 2 MACs: mEMAC (newer, present on
Layerscape and PowerPC T series) and dTSEC/TGEC (older, present on
PowerPC P series). I only have handy access to the mEMAC, and this adds
support for MAC counters for those platforms.

MAC counters are necessary for any kind of low-level debugging, and
currently there is no mechanism to dump them.

Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Link: https://patch.msgid.link/20251122115931.151719-1-vladimir.oltean@nxp.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 7241d80e
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -467,6 +467,47 @@ static int dpaa_set_coalesce(struct net_device *dev,
	return res;
}

static void dpaa_get_pause_stats(struct net_device *net_dev,
				 struct ethtool_pause_stats *s)
{
	struct dpaa_priv *priv = netdev_priv(net_dev);
	struct mac_device *mac_dev = priv->mac_dev;

	if (mac_dev->get_pause_stats)
		mac_dev->get_pause_stats(mac_dev->fman_mac, s);
}

static void dpaa_get_rmon_stats(struct net_device *net_dev,
				struct ethtool_rmon_stats *s,
				const struct ethtool_rmon_hist_range **ranges)
{
	struct dpaa_priv *priv = netdev_priv(net_dev);
	struct mac_device *mac_dev = priv->mac_dev;

	if (mac_dev->get_rmon_stats)
		mac_dev->get_rmon_stats(mac_dev->fman_mac, s, ranges);
}

static void dpaa_get_eth_ctrl_stats(struct net_device *net_dev,
				    struct ethtool_eth_ctrl_stats *s)
{
	struct dpaa_priv *priv = netdev_priv(net_dev);
	struct mac_device *mac_dev = priv->mac_dev;

	if (mac_dev->get_eth_ctrl_stats)
		mac_dev->get_eth_ctrl_stats(mac_dev->fman_mac, s);
}

static void dpaa_get_eth_mac_stats(struct net_device *net_dev,
				   struct ethtool_eth_mac_stats *s)
{
	struct dpaa_priv *priv = netdev_priv(net_dev);
	struct mac_device *mac_dev = priv->mac_dev;

	if (mac_dev->get_eth_mac_stats)
		mac_dev->get_eth_mac_stats(mac_dev->fman_mac, s);
}

const struct ethtool_ops dpaa_ethtool_ops = {
	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
				     ETHTOOL_COALESCE_RX_MAX_FRAMES,
@@ -487,4 +528,8 @@ const struct ethtool_ops dpaa_ethtool_ops = {
	.get_ts_info = dpaa_get_ts_info,
	.get_coalesce = dpaa_get_coalesce,
	.set_coalesce = dpaa_set_coalesce,
	.get_pause_stats = dpaa_get_pause_stats,
	.get_rmon_stats = dpaa_get_rmon_stats,
	.get_eth_ctrl_stats = dpaa_get_eth_ctrl_stats,
	.get_eth_mac_stats = dpaa_get_eth_mac_stats,
};
+87 −0
Original line number Diff line number Diff line
@@ -900,6 +900,89 @@ static int memac_set_exception(struct fman_mac *memac,
	return 0;
}

static u64 memac_read64(void __iomem *reg)
{
	u32 low, high, tmp;

	do {
		high = ioread32be(reg + 4);
		low = ioread32be(reg);
		tmp = ioread32be(reg + 4);
	} while (high != tmp);

	return ((u64)high << 32) | low;
}

static void memac_get_pause_stats(struct fman_mac *memac,
				  struct ethtool_pause_stats *s)
{
	s->tx_pause_frames = memac_read64(&memac->regs->txpf_l);
	s->rx_pause_frames = memac_read64(&memac->regs->rxpf_l);
}

static const struct ethtool_rmon_hist_range memac_rmon_ranges[] = {
	{   64,   64 },
	{   65,  127 },
	{  128,  255 },
	{  256,  511 },
	{  512, 1023 },
	{ 1024, 1518 },
	{ 1519, 9600 },
	{},
};

static void memac_get_rmon_stats(struct fman_mac *memac,
				 struct ethtool_rmon_stats *s,
				 const struct ethtool_rmon_hist_range **ranges)
{
	s->undersize_pkts = memac_read64(&memac->regs->rund_l);
	s->oversize_pkts = memac_read64(&memac->regs->rovr_l);
	s->fragments = memac_read64(&memac->regs->rfrg_l);
	s->jabbers = memac_read64(&memac->regs->rjbr_l);

	s->hist[0] = memac_read64(&memac->regs->r64_l);
	s->hist[1] = memac_read64(&memac->regs->r127_l);
	s->hist[2] = memac_read64(&memac->regs->r255_l);
	s->hist[3] = memac_read64(&memac->regs->r511_l);
	s->hist[4] = memac_read64(&memac->regs->r1023_l);
	s->hist[5] = memac_read64(&memac->regs->r1518_l);
	s->hist[6] = memac_read64(&memac->regs->r1519x_l);

	s->hist_tx[0] = memac_read64(&memac->regs->t64_l);
	s->hist_tx[1] = memac_read64(&memac->regs->t127_l);
	s->hist_tx[2] = memac_read64(&memac->regs->t255_l);
	s->hist_tx[3] = memac_read64(&memac->regs->t511_l);
	s->hist_tx[4] = memac_read64(&memac->regs->t1023_l);
	s->hist_tx[5] = memac_read64(&memac->regs->t1518_l);
	s->hist_tx[6] = memac_read64(&memac->regs->t1519x_l);

	*ranges = memac_rmon_ranges;
}

static void memac_get_eth_ctrl_stats(struct fman_mac *memac,
				     struct ethtool_eth_ctrl_stats *s)
{
	s->MACControlFramesTransmitted = memac_read64(&memac->regs->tcnp_l);
	s->MACControlFramesReceived = memac_read64(&memac->regs->rcnp_l);
}

static void memac_get_eth_mac_stats(struct fman_mac *memac,
				    struct ethtool_eth_mac_stats *s)
{
	s->FramesTransmittedOK = memac_read64(&memac->regs->tfrm_l);
	s->FramesReceivedOK = memac_read64(&memac->regs->rfrm_l);
	s->FrameCheckSequenceErrors = memac_read64(&memac->regs->rfcs_l);
	s->AlignmentErrors = memac_read64(&memac->regs->raln_l);
	s->OctetsTransmittedOK = memac_read64(&memac->regs->teoct_l);
	s->FramesLostDueToIntMACXmitError = memac_read64(&memac->regs->terr_l);
	s->OctetsReceivedOK = memac_read64(&memac->regs->reoct_l);
	s->FramesLostDueToIntMACRcvError = memac_read64(&memac->regs->rdrntp_l);
	s->MulticastFramesXmittedOK = memac_read64(&memac->regs->tmca_l);
	s->BroadcastFramesXmittedOK = memac_read64(&memac->regs->tbca_l);
	s->MulticastFramesReceivedOK = memac_read64(&memac->regs->rmca_l);
	s->BroadcastFramesReceivedOK = memac_read64(&memac->regs->rbca_l);
}

static int memac_init(struct fman_mac *memac)
{
	struct memac_cfg *memac_drv_param;
@@ -1092,6 +1175,10 @@ int memac_initialization(struct mac_device *mac_dev,
	mac_dev->set_tstamp		= memac_set_tstamp;
	mac_dev->enable			= memac_enable;
	mac_dev->disable		= memac_disable;
	mac_dev->get_pause_stats	= memac_get_pause_stats;
	mac_dev->get_rmon_stats		= memac_get_rmon_stats;
	mac_dev->get_eth_ctrl_stats	= memac_get_eth_ctrl_stats;
	mac_dev->get_eth_mac_stats	= memac_get_eth_mac_stats;

	mac_dev->fman_mac = memac_config(mac_dev, params);
	if (!mac_dev->fman_mac)
+14 −0
Original line number Diff line number Diff line
@@ -16,6 +16,11 @@
#include "fman.h"
#include "fman_mac.h"

struct ethtool_eth_ctrl_stats;
struct ethtool_eth_mac_stats;
struct ethtool_pause_stats;
struct ethtool_rmon_stats;
struct ethtool_rmon_hist_range;
struct fman_mac;
struct mac_priv_s;

@@ -46,6 +51,15 @@ struct mac_device {
				 enet_addr_t *eth_addr);
	int (*remove_hash_mac_addr)(struct fman_mac *mac_dev,
				    enet_addr_t *eth_addr);
	void (*get_pause_stats)(struct fman_mac *memac,
				struct ethtool_pause_stats *s);
	void (*get_rmon_stats)(struct fman_mac *memac,
			       struct ethtool_rmon_stats *s,
			       const struct ethtool_rmon_hist_range **ranges);
	void (*get_eth_ctrl_stats)(struct fman_mac *memac,
				   struct ethtool_eth_ctrl_stats *s);
	void (*get_eth_mac_stats)(struct fman_mac *memac,
				  struct ethtool_eth_mac_stats *s);

	void (*update_speed)(struct mac_device *mac_dev, int speed);