[PATCH net-next 3/5] net: dpaa2-mac: export standard statistics
From: Ioana Ciornei <ioana.ciornei@nxp.com>
Date: 2026-02-25 15:07:37
Also in:
linux-kselftest, lkml
Subsystem:
dpaa2 ethernet driver, dpaa2 ethernet switch driver, networking drivers, the rest · Maintainers:
Ioana Ciornei, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Take advantage of all the newly added MAC counters available through the MC API and export them through the standard statistics structures - rmon, eth-ctrl, eth-mac and pause. A new version based feature is added into dpaa2-mac - DPAA2_MAC_FEATURE_STANDARD_STATS - and based on the two memory zones needed for gathering the MAC counters are setup for each statistics group. The dpmac_counter structure is extended with a new field - size_t offset - which is being used to instruct the dpaa2_mac_transfer_stats() function where exactly to store a counter value inside the standard statistics structure. The newly added support is used both in the dpaa2-eth driver as well as the dpaa2-switch one. Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com> --- .../ethernet/freescale/dpaa2/dpaa2-ethtool.c | 59 +++++- .../net/ethernet/freescale/dpaa2/dpaa2-mac.c | 192 ++++++++++++++++++ .../net/ethernet/freescale/dpaa2/dpaa2-mac.h | 13 ++ .../freescale/dpaa2/dpaa2-switch-ethtool.c | 45 +++- 4 files changed, 307 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c
index baab4f1c908d..6f3b15a404fb 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c@@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* Copyright 2014-2016 Freescale Semiconductor Inc. - * Copyright 2016-2022 NXP + * Copyright 2016-2022, 2024-2026 NXP */ #include <linux/net_tstamp.h>
@@ -938,6 +938,59 @@ static void dpaa2_eth_get_channels(struct net_device *net_dev, channels->other_count; } +static void dpaa2_eth_get_rmon_stats(struct net_device *net_dev, + struct ethtool_rmon_stats *rmon_stats, + const struct ethtool_rmon_hist_range **ranges) +{ + struct dpaa2_eth_priv *priv = netdev_priv(net_dev); + + mutex_lock(&priv->mac_lock); + + if (dpaa2_eth_has_mac(priv)) + dpaa2_mac_get_rmon_stats(priv->mac, rmon_stats, ranges); + + mutex_unlock(&priv->mac_lock); +} + +static void dpaa2_eth_get_pause_stats(struct net_device *net_dev, + struct ethtool_pause_stats *pause_stats) +{ + struct dpaa2_eth_priv *priv = netdev_priv(net_dev); + + mutex_lock(&priv->mac_lock); + + if (dpaa2_eth_has_mac(priv)) + dpaa2_mac_get_pause_stats(priv->mac, pause_stats); + + mutex_unlock(&priv->mac_lock); +} + +static void dpaa2_eth_get_ctrl_stats(struct net_device *net_dev, + struct ethtool_eth_ctrl_stats *ctrl_stats) +{ + struct dpaa2_eth_priv *priv = netdev_priv(net_dev); + + mutex_lock(&priv->mac_lock); + + if (dpaa2_eth_has_mac(priv)) + dpaa2_mac_get_ctrl_stats(priv->mac, ctrl_stats); + + mutex_unlock(&priv->mac_lock); +} + +static void dpaa2_eth_get_eth_mac_stats(struct net_device *net_dev, + struct ethtool_eth_mac_stats *eth_mac_stats) +{ + struct dpaa2_eth_priv *priv = netdev_priv(net_dev); + + mutex_lock(&priv->mac_lock); + + if (dpaa2_eth_has_mac(priv)) + dpaa2_mac_get_eth_mac_stats(priv->mac, eth_mac_stats); + + mutex_unlock(&priv->mac_lock); +} + const struct ethtool_ops dpaa2_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS | ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
@@ -962,4 +1015,8 @@ const struct ethtool_ops dpaa2_ethtool_ops = { .get_coalesce = dpaa2_eth_get_coalesce, .set_coalesce = dpaa2_eth_set_coalesce, .get_channels = dpaa2_eth_get_channels, + .get_rmon_stats = dpaa2_eth_get_rmon_stats, + .get_pause_stats = dpaa2_eth_get_pause_stats, + .get_eth_ctrl_stats = dpaa2_eth_get_ctrl_stats, + .get_eth_mac_stats = dpaa2_eth_get_eth_mac_stats, };
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
index 63dc597dbd7c..abdac6ce7bc4 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c@@ -18,20 +18,43 @@ #define DPMAC_STATS_BUNDLE_VER_MAJOR 4 #define DPMAC_STATS_BUNDLE_VER_MINOR 10 +#define DPMAC_STANDARD_STATS_VER_MAJOR 4 +#define DPMAC_STANDARD_STATS_VER_MINOR 11 + #define DPAA2_MAC_FEATURE_PROTOCOL_CHANGE BIT(0) #define DPAA2_MAC_FEATURE_STATS_BUNDLE BIT(1) +#define DPAA2_MAC_FEATURE_STANDARD_STATS BIT(2) struct dpmac_counter { enum dpmac_counter_id id; + size_t offset; const char *name; }; +#define DPMAC_COUNTER(counter_id, struct_name, struct_offset) \ + { \ + .id = counter_id, \ + .offset = offsetof(struct_name, struct_offset), \ + } + #define DPMAC_UNSTRUCTURED_COUNTER(counter_id, counter_name) \ { \ .id = counter_id, \ .name = counter_name, \ } +#define DPMAC_RMON_COUNTER(counter_id, struct_offset) \ + DPMAC_COUNTER(counter_id, struct ethtool_rmon_stats, struct_offset) + +#define DPMAC_PAUSE_COUNTER(counter_id, struct_offset) \ + DPMAC_COUNTER(counter_id, struct ethtool_pause_stats, struct_offset) + +#define DPMAC_CTRL_COUNTER(counter_id, struct_offset) \ + DPMAC_COUNTER(counter_id, struct ethtool_eth_ctrl_stats, struct_offset) + +#define DPMAC_MAC_COUNTER(counter_id, struct_offset) \ + DPMAC_COUNTER(counter_id, struct ethtool_eth_mac_stats, struct_offset) + static const struct dpmac_counter dpaa2_mac_ethtool_stats[] = { DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_ALL_FRAME, "[mac] rx all frames"), DPMAC_UNSTRUCTURED_COUNTER(DPMAC_CNT_ING_GOOD_FRAME, "[mac] rx frames ok"),
@@ -65,6 +88,60 @@ static const struct dpmac_counter dpaa2_mac_ethtool_stats[] = { #define DPAA2_MAC_NUM_ETHTOOL_STATS ARRAY_SIZE(dpaa2_mac_ethtool_stats) +static const struct dpmac_counter dpaa2_mac_rmon_stats[] = { + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_64, hist[0]), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_127, hist[1]), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_255, hist[2]), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_511, hist[3]), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_1023, hist[4]), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_1518, hist[5]), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAME_1519_MAX, hist[6]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_64, hist_tx[0]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_127, hist_tx[1]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_255, hist_tx[2]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_511, hist_tx[3]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_1023, hist_tx[4]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_1518, hist_tx[5]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_FRAME_1519_MAX, hist_tx[6]), + DPMAC_RMON_COUNTER(DPMAC_CNT_EGR_UNDERSIZED, undersize_pkts), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_OVERSIZED, oversize_pkts), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_FRAG, fragments), + DPMAC_RMON_COUNTER(DPMAC_CNT_ING_JABBER, jabbers), +}; + +#define DPAA2_MAC_NUM_RMON_STATS ARRAY_SIZE(dpaa2_mac_rmon_stats) + +static const struct dpmac_counter dpaa2_mac_pause_stats[] = { + DPMAC_PAUSE_COUNTER(DPMAC_CNT_ING_VALID_PAUSE_FRAME, rx_pause_frames), + DPMAC_PAUSE_COUNTER(DPMAC_CNT_EGR_VALID_PAUSE_FRAME, tx_pause_frames), +}; + +#define DPAA2_MAC_NUM_PAUSE_STATS ARRAY_SIZE(dpaa2_mac_pause_stats) + +static const struct dpmac_counter dpaa2_mac_eth_ctrl_stats[] = { + DPMAC_CTRL_COUNTER(DPMAC_CNT_ING_CONTROL_FRAME, MACControlFramesReceived), + DPMAC_CTRL_COUNTER(DPMAC_CNT_EGR_CONTROL_FRAME, MACControlFramesTransmitted), +}; + +#define DPAA2_MAC_NUM_ETH_CTRL_STATS ARRAY_SIZE(dpaa2_mac_eth_ctrl_stats) + +static const struct dpmac_counter dpaa2_mac_eth_mac_stats[] = { + DPMAC_MAC_COUNTER(DPMAC_CNT_EGR_GOOD_FRAME, FramesTransmittedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_GOOD_FRAME, FramesReceivedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_FCS_ERR, FrameCheckSequenceErrors), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_ALIGN_ERR, AlignmentErrors), + DPMAC_MAC_COUNTER(DPMAC_CNT_EGR_ALL_BYTE, OctetsTransmittedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_EGR_ERR_FRAME, FramesLostDueToIntMACXmitError), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_ALL_BYTE, OctetsReceivedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_FRAME_DISCARD_NOT_TRUNC, FramesLostDueToIntMACRcvError), + DPMAC_MAC_COUNTER(DPMAC_CNT_EGR_MCAST_FRAME, MulticastFramesXmittedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_EGR_BCAST_FRAME, BroadcastFramesXmittedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_MCAST_FRAME, MulticastFramesReceivedOK), + DPMAC_MAC_COUNTER(DPMAC_CNT_ING_BCAST_FRAME, BroadcastFramesReceivedOK), +}; + +#define DPAA2_MAC_NUM_ETH_MAC_STATS ARRAY_SIZE(dpaa2_mac_eth_mac_stats) + static void dpaa2_mac_setup_stats(struct dpaa2_mac *mac, struct dpaa2_mac_stats *stats, size_t num_stats, const struct dpmac_counter *counters) {
@@ -150,6 +227,10 @@ static void dpaa2_mac_detect_features(struct dpaa2_mac *mac) if (dpaa2_mac_cmp_ver(mac, DPMAC_STATS_BUNDLE_VER_MAJOR, DPMAC_STATS_BUNDLE_VER_MINOR) >= 0) mac->features |= DPAA2_MAC_FEATURE_STATS_BUNDLE; + + if (dpaa2_mac_cmp_ver(mac, DPMAC_STANDARD_STATS_VER_MAJOR, + DPMAC_STANDARD_STATS_VER_MINOR) >= 0) + mac->features |= DPAA2_MAC_FEATURE_STANDARD_STATS; } static int phy_mode(enum dpmac_eth_if eth_if, phy_interface_t *if_mode)
@@ -626,6 +707,20 @@ int dpaa2_mac_open(struct dpaa2_mac *mac) dpaa2_mac_setup_stats(mac, &mac->ethtool_stats, DPAA2_MAC_NUM_ETHTOOL_STATS, dpaa2_mac_ethtool_stats); + if (mac->features & DPAA2_MAC_FEATURE_STANDARD_STATS) { + dpaa2_mac_setup_stats(mac, &mac->rmon_stats, + DPAA2_MAC_NUM_RMON_STATS, dpaa2_mac_rmon_stats); + + dpaa2_mac_setup_stats(mac, &mac->pause_stats, + DPAA2_MAC_NUM_PAUSE_STATS, dpaa2_mac_pause_stats); + + dpaa2_mac_setup_stats(mac, &mac->eth_ctrl_stats, + DPAA2_MAC_NUM_ETH_CTRL_STATS, dpaa2_mac_eth_ctrl_stats); + + dpaa2_mac_setup_stats(mac, &mac->eth_mac_stats, + DPAA2_MAC_NUM_ETH_MAC_STATS, dpaa2_mac_eth_mac_stats); + } + return 0; err_close_dpmac:
@@ -640,11 +735,108 @@ void dpaa2_mac_close(struct dpaa2_mac *mac) if (mac->features & DPAA2_MAC_FEATURE_STATS_BUNDLE) dpaa2_mac_clear_stats(mac, &mac->ethtool_stats, DPAA2_MAC_NUM_ETHTOOL_STATS); + if (mac->features & DPAA2_MAC_FEATURE_STANDARD_STATS) { + dpaa2_mac_clear_stats(mac, &mac->rmon_stats, DPAA2_MAC_NUM_RMON_STATS); + dpaa2_mac_clear_stats(mac, &mac->pause_stats, DPAA2_MAC_NUM_PAUSE_STATS); + dpaa2_mac_clear_stats(mac, &mac->eth_ctrl_stats, DPAA2_MAC_NUM_ETH_CTRL_STATS); + dpaa2_mac_clear_stats(mac, &mac->eth_mac_stats, DPAA2_MAC_NUM_ETH_MAC_STATS); + } + dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle); if (mac->fw_node) fwnode_handle_put(mac->fw_node); } +static void dpaa2_mac_transfer_stats(const struct dpmac_counter *counters, + size_t num_counters, void *s, + u64 *cnt_values) +{ + for (size_t i = 0; i < num_counters; i++) { + u64 *p = s + counters[i].offset; + + *p = le64_to_cpu(cnt_values[i]); + } +} + +static const struct ethtool_rmon_hist_range dpaa2_mac_rmon_ranges[] = { + { 64, 64 }, + { 65, 127 }, + { 128, 255 }, + { 256, 511 }, + { 512, 1023 }, + { 1024, 1518 }, + { 1519, DPAA2_ETH_MFL }, + {}, +}; + +static void dpaa2_mac_get_standard_stats(struct dpaa2_mac *mac, struct dpaa2_mac_stats *stats, + size_t num_cnt, const struct dpmac_counter *counters, + void *s) +{ + struct device *dev = mac->net_dev->dev.parent; + struct fsl_mc_device *dpmac_dev = mac->mc_dev; + int err; + + if (!(mac->features & DPAA2_MAC_FEATURE_STANDARD_STATS)) + return; + + if (!stats->idx_dma_mem || !stats->values_dma_mem) + return; + + err = dpmac_get_statistics(mac->mc_io, 0, dpmac_dev->mc_handle, + stats->idx_iova, stats->values_iova, + num_cnt); + if (err) { + netdev_err(mac->net_dev, "%s: dpmac_get_statistics() = %d\n", + __func__, err); + return; + } + + dma_sync_single_for_cpu(dev, stats->values_iova, num_cnt * sizeof(u64), + DMA_FROM_DEVICE); + + dpaa2_mac_transfer_stats(counters, num_cnt, s, stats->values_dma_mem); +} + +void dpaa2_mac_get_rmon_stats(struct dpaa2_mac *mac, struct ethtool_rmon_stats *s, + const struct ethtool_rmon_hist_range **ranges) +{ + if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE) + return; + + dpaa2_mac_get_standard_stats(mac, &mac->rmon_stats, DPAA2_MAC_NUM_RMON_STATS, + dpaa2_mac_rmon_stats, s); + + *ranges = dpaa2_mac_rmon_ranges; +} + +void dpaa2_mac_get_pause_stats(struct dpaa2_mac *mac, struct ethtool_pause_stats *s) +{ + if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE) + return; + + dpaa2_mac_get_standard_stats(mac, &mac->pause_stats, DPAA2_MAC_NUM_PAUSE_STATS, + dpaa2_mac_pause_stats, s); +} + +void dpaa2_mac_get_ctrl_stats(struct dpaa2_mac *mac, struct ethtool_eth_ctrl_stats *s) +{ + if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE) + return; + + dpaa2_mac_get_standard_stats(mac, &mac->eth_ctrl_stats, DPAA2_MAC_NUM_ETH_CTRL_STATS, + dpaa2_mac_eth_ctrl_stats, s); +} + +void dpaa2_mac_get_eth_mac_stats(struct dpaa2_mac *mac, struct ethtool_eth_mac_stats *s) +{ + if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE) + return; + + dpaa2_mac_get_standard_stats(mac, &mac->eth_mac_stats, DPAA2_MAC_NUM_ETH_MAC_STATS, + dpaa2_mac_eth_mac_stats, s); +} + int dpaa2_mac_get_sset_count(void) { return DPAA2_MAC_NUM_ETHTOOL_STATS;
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
index 386286209606..eeb632b9da0a 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h@@ -36,6 +36,10 @@ struct dpaa2_mac { struct phy *serdes_phy; struct dpaa2_mac_stats ethtool_stats; + struct dpaa2_mac_stats rmon_stats; + struct dpaa2_mac_stats pause_stats; + struct dpaa2_mac_stats eth_ctrl_stats; + struct dpaa2_mac_stats eth_mac_stats; }; static inline bool dpaa2_mac_is_type_phy(struct dpaa2_mac *mac)
@@ -61,6 +65,15 @@ void dpaa2_mac_get_strings(u8 **data); void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data); +void dpaa2_mac_get_rmon_stats(struct dpaa2_mac *mac, struct ethtool_rmon_stats *s, + const struct ethtool_rmon_hist_range **ranges); + +void dpaa2_mac_get_pause_stats(struct dpaa2_mac *mac, struct ethtool_pause_stats *s); + +void dpaa2_mac_get_ctrl_stats(struct dpaa2_mac *mac, struct ethtool_eth_ctrl_stats *s); + +void dpaa2_mac_get_eth_mac_stats(struct dpaa2_mac *mac, struct ethtool_eth_mac_stats *s); + void dpaa2_mac_start(struct dpaa2_mac *mac); void dpaa2_mac_stop(struct dpaa2_mac *mac);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c
index a888f6e6e9b0..3203873fae85 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c@@ -3,7 +3,7 @@ * DPAA2 Ethernet Switch ethtool support * * Copyright 2014-2016 Freescale Semiconductor Inc. - * Copyright 2017-2018 NXP + * Copyright 2017-2018, 2024-2026 NXP * */
@@ -210,6 +210,46 @@ static void dpaa2_switch_ethtool_get_stats(struct net_device *netdev, mutex_unlock(&port_priv->mac_lock); } +static void dpaa2_switch_get_rmon_stats(struct net_device *netdev, + struct ethtool_rmon_stats *rmon_stats, + const struct ethtool_rmon_hist_range **ranges) +{ + struct ethsw_port_priv *port_priv = netdev_priv(netdev); + + mutex_lock(&port_priv->mac_lock); + + if (dpaa2_switch_port_has_mac(port_priv)) + dpaa2_mac_get_rmon_stats(port_priv->mac, rmon_stats, ranges); + + mutex_unlock(&port_priv->mac_lock); +} + +static void dpaa2_switch_get_ctrl_stats(struct net_device *net_dev, + struct ethtool_eth_ctrl_stats *ctrl_stats) +{ + struct ethsw_port_priv *port_priv = netdev_priv(net_dev); + + mutex_lock(&port_priv->mac_lock); + + if (dpaa2_switch_port_has_mac(port_priv)) + dpaa2_mac_get_ctrl_stats(port_priv->mac, ctrl_stats); + + mutex_unlock(&port_priv->mac_lock); +} + +static void dpaa2_switch_get_eth_mac_stats(struct net_device *net_dev, + struct ethtool_eth_mac_stats *eth_mac_stats) +{ + struct ethsw_port_priv *port_priv = netdev_priv(net_dev); + + mutex_lock(&port_priv->mac_lock); + + if (dpaa2_switch_port_has_mac(port_priv)) + dpaa2_mac_get_eth_mac_stats(port_priv->mac, eth_mac_stats); + + mutex_unlock(&port_priv->mac_lock); +} + const struct ethtool_ops dpaa2_switch_port_ethtool_ops = { .get_drvinfo = dpaa2_switch_get_drvinfo, .get_link = ethtool_op_get_link,
@@ -218,4 +258,7 @@ const struct ethtool_ops dpaa2_switch_port_ethtool_ops = { .get_strings = dpaa2_switch_ethtool_get_strings, .get_ethtool_stats = dpaa2_switch_ethtool_get_stats, .get_sset_count = dpaa2_switch_ethtool_get_sset_count, + .get_rmon_stats = dpaa2_switch_get_rmon_stats, + .get_eth_ctrl_stats = dpaa2_switch_get_ctrl_stats, + .get_eth_mac_stats = dpaa2_switch_get_eth_mac_stats, };
--
2.25.1