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: Vladimir Oltean <vladimir.oltean@nxp.com>
Link: https://patch.msgid.link/20251122115931.151719-1-vladimir.oltean@nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Vladimir Oltean
2025-11-22 13:59:31 +02:00
committed by Jakub Kicinski
parent 7241d80e77
commit 37a96c2009
3 changed files with 146 additions and 0 deletions

View File

@@ -467,6 +467,47 @@ revert_values:
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,
};

View File

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

View File

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