Commit 4a38cde6 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'ethtool-get_ts_stats-for-dsa-and-ocelot-driver'

Vladimir Oltean says:

====================
ethtool get_ts_stats() for DSA and ocelot driver

After a recent patch set with fixes and general restructuring, Jakub asked
for the Felix DSA driver to start reporting standardized statistics
for hardware timestamping:
https://lore.kernel.org/netdev/20241207180640.12da60ed@kernel.org/

Testing follows the same procedure as in the aforementioned series, with PTP
packet loss induced through taprio:

$ ethtool -I --show-time-stamping swp3
Time stamping parameters for swp3:
Capabilities:
        hardware-transmit
        software-transmit
        hardware-receive
        software-receive
        software-system-clock
        hardware-raw-clock
PTP Hardware Clock: 1
Hardware Transmit Timestamp Modes:
        off
        on
        onestep-sync
Hardware Receive Filter Modes:
        none
        ptpv2-l4-event
        ptpv2-l2-event
        ptpv2-event
Statistics:
  tx_pkts: 14591
  tx_lost: 85
  tx_err: 0

v1: https://lore.kernel.org/20241213140852.1254063-1-vladimir.oltean@nxp.com/
====================

Link: https://patch.msgid.link/20250116104628.123555-1-vladimir.oltean@nxp.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 19e1e17f e777a4b3
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -842,6 +842,9 @@ attribute-sets:
      -
        name: tx-err
        type: uint
      -
        name: tx-onestep-pkts-unconfirmed
        type: uint
  -
    name: ts-hwtstamp-provider
    attr-cnt-name: __ethtool-a-ts-hwtstamp-provider-cnt
+11 −5
Original line number Diff line number Diff line
@@ -1281,11 +1281,17 @@ would be empty (no bit set).

Additional hardware timestamping statistics response contents:

  =====================================  ======  ===================================
  ``ETHTOOL_A_TS_STAT_TX_PKTS``          uint    Packets with Tx HW timestamps
  ``ETHTOOL_A_TS_STAT_TX_LOST``          uint    Tx HW timestamp not arrived count
  ``ETHTOOL_A_TS_STAT_TX_ERR``           uint    HW error request Tx timestamp count
  =====================================  ======  ===================================
  ==================================================  ======  =====================
  ``ETHTOOL_A_TS_STAT_TX_PKTS``                       uint    Packets with Tx
                                                              HW timestamps
  ``ETHTOOL_A_TS_STAT_TX_LOST``                       uint    Tx HW timestamp
                                                              not arrived count
  ``ETHTOOL_A_TS_STAT_TX_ERR``                        uint    HW error request
                                                              Tx timestamp count
  ``ETHTOOL_A_TS_STAT_TX_ONESTEP_PKTS_UNCONFIRMED``   uint    Packets with one-step
                                                              HW TX timestamps with
                                                              unconfirmed delivery
  ==================================================  ======  =====================

CABLE_TEST
==========
+9 −0
Original line number Diff line number Diff line
@@ -1316,6 +1316,14 @@ static void felix_get_eth_phy_stats(struct dsa_switch *ds, int port,
	ocelot_port_get_eth_phy_stats(ocelot, port, phy_stats);
}

static void felix_get_ts_stats(struct dsa_switch *ds, int port,
			       struct ethtool_ts_stats *ts_stats)
{
	struct ocelot *ocelot = ds->priv;

	ocelot_port_get_ts_stats(ocelot, port, ts_stats);
}

static void felix_get_strings(struct dsa_switch *ds, int port,
			      u32 stringset, u8 *data)
{
@@ -2237,6 +2245,7 @@ static const struct dsa_switch_ops felix_switch_ops = {
	.get_stats64			= felix_get_stats64,
	.get_pause_stats		= felix_get_pause_stats,
	.get_rmon_stats			= felix_get_rmon_stats,
	.get_ts_stats			= felix_get_ts_stats,
	.get_eth_ctrl_stats		= felix_get_eth_ctrl_stats,
	.get_eth_mac_stats		= felix_get_eth_mac_stats,
	.get_eth_phy_stats		= felix_get_eth_phy_stats,
+11 −0
Original line number Diff line number Diff line
@@ -993,6 +993,16 @@ static int ocelot_port_get_ts_info(struct net_device *dev,
	return ocelot_get_ts_info(ocelot, port, info);
}

static void ocelot_port_ts_stats(struct net_device *dev,
				 struct ethtool_ts_stats *ts_stats)
{
	struct ocelot_port_private *priv = netdev_priv(dev);
	struct ocelot *ocelot = priv->port.ocelot;
	int port = priv->port.index;

	ocelot_port_get_ts_stats(ocelot, port, ts_stats);
}

static const struct ethtool_ops ocelot_ethtool_ops = {
	.get_strings		= ocelot_port_get_strings,
	.get_ethtool_stats	= ocelot_port_get_ethtool_stats,
@@ -1000,6 +1010,7 @@ static const struct ethtool_ops ocelot_ethtool_ops = {
	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
	.set_link_ksettings	= phy_ethtool_set_link_ksettings,
	.get_ts_info		= ocelot_port_get_ts_info,
	.get_ts_stats		= ocelot_port_ts_stats,
};

static void ocelot_port_attr_stp_state_set(struct ocelot *ocelot, int port,
+42 −11
Original line number Diff line number Diff line
@@ -680,9 +680,14 @@ static int ocelot_port_queue_ptp_tx_skb(struct ocelot *ocelot, int port,
	skb_queue_walk_safe(&ocelot_port->tx_skbs, skb, skb_tmp) {
		if (time_before(OCELOT_SKB_CB(skb)->ptp_tx_time +
				OCELOT_PTP_TX_TSTAMP_TIMEOUT, jiffies)) {
			dev_warn_ratelimited(ocelot->dev,
			u64_stats_update_begin(&ocelot_port->ts_stats->syncp);
			ocelot_port->ts_stats->lost++;
			u64_stats_update_end(&ocelot_port->ts_stats->syncp);

			dev_dbg_ratelimited(ocelot->dev,
					    "port %d invalidating stale timestamp ID %u which seems lost\n",
					    port, OCELOT_SKB_CB(skb)->ts_id);

			__skb_unlink(skb, &ocelot_port->tx_skbs);
			kfree_skb(skb);
			ocelot->ptp_skbs_in_flight--;
@@ -748,13 +753,20 @@ int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port,
		return 0;

	ptp_class = ptp_classify_raw(skb);
	if (ptp_class == PTP_CLASS_NONE)
		return -EINVAL;
	if (ptp_class == PTP_CLASS_NONE) {
		err = -EINVAL;
		goto error;
	}

	/* Store ptp_cmd in OCELOT_SKB_CB(skb)->ptp_cmd */
	if (ptp_cmd == IFH_REW_OP_ORIGIN_PTP) {
		if (ocelot_ptp_is_onestep_sync(skb, ptp_class)) {
			OCELOT_SKB_CB(skb)->ptp_cmd = ptp_cmd;

			u64_stats_update_begin(&ocelot_port->ts_stats->syncp);
			ocelot_port->ts_stats->onestep_pkts_unconfirmed++;
			u64_stats_update_end(&ocelot_port->ts_stats->syncp);

			return 0;
		}

@@ -764,14 +776,16 @@ int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port,

	if (ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
		*clone = skb_clone_sk(skb);
		if (!(*clone))
			return -ENOMEM;
		if (!(*clone)) {
			err = -ENOMEM;
			goto error;
		}

		/* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */
		err = ocelot_port_queue_ptp_tx_skb(ocelot, port, *clone);
		if (err) {
			kfree_skb(*clone);
			return err;
			goto error;
		}

		skb_shinfo(*clone)->tx_flags |= SKBTX_IN_PROGRESS;
@@ -780,6 +794,12 @@ int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port,
	}

	return 0;

error:
	u64_stats_update_begin(&ocelot_port->ts_stats->syncp);
	ocelot_port->ts_stats->err++;
	u64_stats_update_end(&ocelot_port->ts_stats->syncp);
	return err;
}
EXPORT_SYMBOL(ocelot_port_txtstamp_request);

@@ -816,6 +836,7 @@ void ocelot_get_txtstamp(struct ocelot *ocelot)

	while (budget--) {
		struct skb_shared_hwtstamps shhwtstamps;
		struct ocelot_port *ocelot_port;
		u32 val, id, seqid, txport;
		struct sk_buff *skb_match;
		struct timespec64 ts;
@@ -832,17 +853,27 @@ void ocelot_get_txtstamp(struct ocelot *ocelot)
		id = SYS_PTP_STATUS_PTP_MESS_ID_X(val);
		txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);
		seqid = SYS_PTP_STATUS_PTP_MESS_SEQ_ID(val);
		ocelot_port = ocelot->ports[txport];

		/* Retrieve its associated skb */
		skb_match = ocelot_port_dequeue_ptp_tx_skb(ocelot, txport, id,
							   seqid);
		if (!skb_match) {
			dev_warn_ratelimited(ocelot->dev,
			u64_stats_update_begin(&ocelot_port->ts_stats->syncp);
			ocelot_port->ts_stats->err++;
			u64_stats_update_end(&ocelot_port->ts_stats->syncp);

			dev_dbg_ratelimited(ocelot->dev,
					    "port %d received TX timestamp (seqid %d, ts id %u) for packet previously declared stale\n",
					    txport, seqid, id);

			goto next_ts;
		}

		u64_stats_update_begin(&ocelot_port->ts_stats->syncp);
		ocelot_port->ts_stats->pkts++;
		u64_stats_update_end(&ocelot_port->ts_stats->syncp);

		/* Get the h/w timestamp */
		ocelot_get_hwtimestamp(ocelot, &ts);

Loading