Re: [PATCH net-next v6 05/11] net: ti: prueth: Adds ethtool support for ICSSM PRUETH Driver

From: ALOK TIWARI
Date: Sat May 03 2025 - 05:32:37 EST




On 23-04-2025 12:53, Parvathi Pudi wrote:
From: Roger Quadros <rogerq@xxxxxx>

Changes for enabling ethtool support for the newly added PRU Ethernet
interfaces. Extends the support for statistics collection from PRU internal
memory and displays it in the user space. Along with statistics,
enable/disable of features, configuring link speed etc.are now supported.

etc.are -> etc. are


The firmware running on PRU maintains statistics in internal data memory.
When requested ethtool collects all the statistics for the specified
interface and displays it in the user space.


--- a/drivers/net/ethernet/ti/Makefile
+++ b/drivers/net/ethernet/ti/Makefile
@@ -4,7 +4,7 @@
#
[clip]
+}
+
+static void icssm_emac_get_regs(struct net_device *ndev,
+ struct ethtool_regs *regs, void *p)
+{
+ struct prueth_emac *emac = netdev_priv(ndev);
+ struct prueth *prueth = emac->prueth;
+
+ regs->version = PRUETH_REG_DUMP_GET_VER(prueth);
+}
+
+static const struct ethtool_rmon_hist_range icssm_emac_rmon_ranges[] = {
+ { 0, 64},
+ { 65, 127},
+ { 128, 255},
+ { 256, 511},
+ { 512, 1023},
+ { 1024, EMAC_MAX_PKTLEN},
+ {}
+};
+
+static void
+icssm_emac_get_rmon_stats(struct net_device *ndev,
+ struct ethtool_rmon_stats *rmon_stats,
+ const struct ethtool_rmon_hist_range **ranges)
+{
+ struct prueth_emac *emac = netdev_priv(ndev);
+ struct port_statistics pstats;
+
+ *ranges = icssm_emac_rmon_ranges;
+ icssm_emac_get_stats(emac, &pstats);
+
+ rmon_stats->undersize_pkts = pstats.rx_undersized_frames;
+ rmon_stats->oversize_pkts = pstats.rx_oversized_frames;

remove extra ' ' before =

+
+ rmon_stats->hist[0] = pstats.tx64byte;
+ rmon_stats->hist[1] = pstats.tx65_127byte;
+ rmon_stats->hist[2] = pstats.tx128_255byte;
+ rmon_stats->hist[3] = pstats.tx256_511byte;
+ rmon_stats->hist[4] = pstats.tx512_1023byte;
+
+ rmon_stats->hist_tx[0] = pstats.rx64byte;
+ rmon_stats->hist_tx[1] = pstats.rx65_127byte;
+ rmon_stats->hist_tx[2] = pstats.rx128_255byte;
+ rmon_stats->hist_tx[3] = pstats.rx256_511byte;
+ rmon_stats->hist_tx[4] = pstats.rx1024byte;
+}
+
+static void
+icssm_emac_get_eth_mac_stats(struct net_device *ndev,
+ struct ethtool_eth_mac_stats *mac_stats)
+{
+ struct prueth_emac *emac = netdev_priv(ndev);
+ struct port_statistics pstats;
+
+ icssm_emac_get_stats(emac, &pstats);
+
+ mac_stats->LateCollisions = pstats.late_coll;
+ mac_stats->SingleCollisionFrames = pstats.single_coll;
+ mac_stats->MultipleCollisionFrames = pstats.multi_coll;
+}
+
+/* Ethtool support for EMAC adapter */
+const struct ethtool_ops emac_ethtool_ops = {
+ .get_drvinfo = icssm_emac_get_drvinfo,
+ .get_link_ksettings = phy_ethtool_get_link_ksettings,
+ .set_link_ksettings = phy_ethtool_set_link_ksettings,
+ .get_link = ethtool_op_get_link,
+ .get_sset_count = icssm_emac_get_sset_count,
+ .get_strings = icssm_emac_get_strings,
+ .get_ethtool_stats = icssm_emac_get_ethtool_stats,
+ .get_regs = icssm_emac_get_regs,
+ .get_rmon_stats = icssm_emac_get_rmon_stats,
+ .get_eth_mac_stats = icssm_emac_get_eth_mac_stats,
+};
+EXPORT_SYMBOL_GPL(emac_ethtool_ops);
diff --git a/drivers/net/ethernet/ti/icssm/icssm_prueth.c b/drivers/net/ethernet/ti/icssm/icssm_prueth.c
index 7aae12383ad3..b37991b04dd1 100644
--- a/drivers/net/ethernet/ti/icssm/icssm_prueth.c
+++ b/drivers/net/ethernet/ti/icssm/icssm_prueth.c
@@ -901,6 +901,8 @@ static int icssm_emac_ndo_open(struct net_device *ndev)
icssm_prueth_emac_config(emac);
+ icssm_emac_set_stats(emac, &emac->stats);
+
ret = icssm_emac_set_boot_pru(emac, ndev);
if (ret)
return ret;
@@ -952,6 +954,8 @@ static int icssm_emac_ndo_stop(struct net_device *ndev)
/* stop the PRU */
rproc_shutdown(emac->pru);
+ icssm_emac_get_stats(emac, &emac->stats);
+
/* free rx interrupts */
free_irq(emac->rx_irq, ndev);
@@ -1045,10 +1049,39 @@ static enum netdev_tx icssm_emac_ndo_start_xmit(struct sk_buff *skb,
return ret;
}
+/**
+ * icssm_emac_ndo_get_stats64 - EMAC get statistics function
+ * @ndev: The EMAC network adapter
+ * @stats: rtnl_link_stats structure
+ *
+ * Called when system wants to get statistics from the device.
+ *
+ */
+static void icssm_emac_ndo_get_stats64(struct net_device *ndev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct prueth_emac *emac = netdev_priv(ndev);
+ struct port_statistics pstats;
+
+ icssm_emac_get_stats(emac, &pstats);
+
+ stats->rx_packets = ndev->stats.rx_packets;
+ stats->rx_bytes = ndev->stats.rx_bytes;
+ stats->tx_packets = ndev->stats.tx_packets;
+ stats->tx_bytes = ndev->stats.tx_bytes;
+ stats->tx_errors = ndev->stats.tx_errors;
+ stats->tx_dropped = ndev->stats.tx_dropped;
+ stats->multicast = pstats.rx_mcast;
+
+ stats->rx_over_errors = ndev->stats.rx_over_errors;
+ stats->rx_length_errors = ndev->stats.rx_length_errors;

remove extra ' ' before =

+}
+
static const struct net_device_ops emac_netdev_ops = {
.ndo_open = icssm_emac_ndo_open,
.ndo_stop = icssm_emac_ndo_stop,
.ndo_start_xmit = icssm_emac_ndo_start_xmit,
+ .ndo_get_stats64 = icssm_emac_ndo_get_stats64,
};
/* get emac_port corresponding to eth_node name */
@@ -1177,6 +1210,7 @@ static int icssm_prueth_netdev_init(struct prueth *prueth,
phy_remove_link_mode(emac->phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT);
ndev->netdev_ops = &emac_netdev_ops;
+ ndev->ethtool_ops = &emac_ethtool_ops;
return 0;
free:
diff --git a/drivers/net/ethernet/ti/icssm/icssm_prueth.h b/drivers/net/ethernet/ti/icssm/icssm_prueth.h
index 3c70dc9c4be0..39ceed0e2d15 100644
--- a/drivers/net/ethernet/ti/icssm/icssm_prueth.h
+++ b/drivers/net/ethernet/ti/icssm/icssm_prueth.h
@@ -27,6 +27,12 @@
#define EMAC_MAX_FRM_SUPPORT (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN + \
ICSSM_LRE_TAG_SIZE)
+#define PRUETH_REG_DUMP_VER 1
+
+/* Encoding: 32-16: Reserved, 16-8: Reg dump version, 8-0: Ethertype */

remove extra ' ' after Ethertype

+#define PRUETH_REG_DUMP_GET_VER(x) ((PRUETH_REG_DUMP_VER << 8) | \
+ ((x)->eth_type))
+
/* PRU Ethernet Type - Ethernet functionality (protocol
* implemented) provided by the PRU firmware being loaded.
*/
@@ -108,6 +114,119 @@ struct prueth_packet_info {
bool timestamp;
};

Thanks,
Alok