Commit 9e8a4434 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'ethtool-introduce-phy-mse-diagnostics-uapi-and-drivers'

Oleksij Rempel says:

====================
ethtool: introduce PHY MSE diagnostics UAPI and drivers

This series introduces a generic kernel-userspace API for retrieving PHY
Mean Square Error (MSE) diagnostics, together with netlink integration,
a fast-path reporting hook in LINKSTATE_GET, and initial driver
implementations for the KSZ9477 and DP83TD510E PHYs.

MSE is defined by the OPEN Alliance "Advanced diagnostic features for
100BASE-T1 automotive Ethernet PHYs" specification [1] as a measure of
slicer error rate, typically used internally to derive the Signal
Quality Indicator (SQI). While SQI is useful as a normalized quality
index, it hides raw measurement data, varies in scaling and thresholds
between vendors, and may not indicate certain failure modes - for
example, cases where autonegotiation would fail even though SQI reports
a good link. In practice, such scenarios can only be investigated in
fixed-link mode; here, MSE can provide an empirically estimated value
indicating conditions under which autonegotiation would not succeed.

Example output with current implementation:
root@DistroKit:~ ethtool lan1
Settings for lan1:
...
        Speed: 1000Mb/s
        Duplex: Full
...
        Link detected: yes
        SQI: 5/7
        MSE: 3/127 (channel: worst)

root@DistroKit:~ ethtool --show-mse lan1
MSE diagnostics for lan1:
MSE Configuration:
        Max Average MSE: 127
        Refresh Rate: 2000000 ps
        Symbols per Sample: 250
        Supported capabilities: average channel-a channel-b channel-c
                                channel-d worst

MSE Snapshot (Channel: a):
        Average MSE: 4

MSE Snapshot (Channel: b):
        Average MSE: 3

MSE Snapshot (Channel: c):
        Average MSE: 2

MSE Snapshot (Channel: d):
        Average MSE: 3

[1] https://opensig.org/wp-content/uploads/2024/01/Advanced_PHY_features_for_automotive_Ethernet_V1.0.pdf
====================

Link: https://patch.msgid.link/20251027122801.982364-1-o.rempel@pengutronix.de


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents ff371a7e fd93ed77
Loading
Loading
Loading
Loading
+86 −0
Original line number Diff line number Diff line
@@ -1823,6 +1823,73 @@ attribute-sets:
        type: uint
        enum: pse-event
        doc: List of events reported by the PSE controller
  -
    name: mse-capabilities
    doc: MSE capabilities attribute set
    attr-cnt-name: --ethtool-a-mse-capabilities-cnt
    attributes:
      -
        name: max-average-mse
        type: uint
      -
        name: max-peak-mse
        type: uint
      -
        name: refresh-rate-ps
        type: uint
      -
        name: num-symbols
        type: uint
  -
    name: mse-snapshot
    doc: MSE snapshot attribute set
    attr-cnt-name: --ethtool-a-mse-snapshot-cnt
    attributes:
      -
        name: average-mse
        type: uint
      -
        name: peak-mse
        type: uint
      -
        name: worst-peak-mse
        type: uint
  -
    name: mse
    attr-cnt-name: --ethtool-a-mse-cnt
    attributes:
      -
        name: header
        type: nest
        nested-attributes: header
      -
        name: capabilities
        type: nest
        nested-attributes: mse-capabilities
      -
        name: channel-a
        type: nest
        nested-attributes: mse-snapshot
      -
        name: channel-b
        type: nest
        nested-attributes: mse-snapshot
      -
        name: channel-c
        type: nest
        nested-attributes: mse-snapshot
      -
        name: channel-d
        type: nest
        nested-attributes: mse-snapshot
      -
        name: worst-channel
        type: nest
        nested-attributes: mse-snapshot
      -
        name: link
        type: nest
        nested-attributes: mse-snapshot

operations:
  enum-model: directional
@@ -2756,6 +2823,25 @@ operations:
        attributes:
          - header
          - context
    -
      name: mse-get
      doc: Get PHY MSE measurement data and capabilities.
      attribute-set: mse
      do: &mse-get-op
        request:
          attributes:
            - header
        reply:
          attributes:
            - header
            - capabilities
            - channel-a
            - channel-b
            - channel-c
            - channel-d
            - worst-channel
            - link
      dump: *mse-get-op

mcast-groups:
  list:
+64 −0
Original line number Diff line number Diff line
@@ -242,6 +242,7 @@ Userspace to kernel:
  ``ETHTOOL_MSG_RSS_SET``               set RSS settings
  ``ETHTOOL_MSG_RSS_CREATE_ACT``        create an additional RSS context
  ``ETHTOOL_MSG_RSS_DELETE_ACT``        delete an additional RSS context
  ``ETHTOOL_MSG_MSE_GET``               get MSE diagnostic data
  ===================================== =================================

Kernel to userspace:
@@ -299,6 +300,7 @@ Kernel to userspace:
  ``ETHTOOL_MSG_RSS_CREATE_ACT_REPLY``     create an additional RSS context
  ``ETHTOOL_MSG_RSS_CREATE_NTF``           additional RSS context created
  ``ETHTOOL_MSG_RSS_DELETE_NTF``           additional RSS context deleted
  ``ETHTOOL_MSG_MSE_GET_REPLY``            MSE diagnostic data
  ======================================== =================================

``GET`` requests are sent by userspace applications to retrieve device
@@ -2458,6 +2460,68 @@ Kernel response contents:

For a description of each attribute, see ``TSCONFIG_GET``.

MSE_GET
=======

Retrieves detailed Mean Square Error (MSE) diagnostic information from the PHY.

Request Contents:

  ====================================  ======  ============================
  ``ETHTOOL_A_MSE_HEADER``              nested  request header
  ====================================  ======  ============================

Kernel Response Contents:

  ====================================  ======  ================================
  ``ETHTOOL_A_MSE_HEADER``              nested  reply header
  ``ETHTOOL_A_MSE_CAPABILITIES``        nested  capability/scale info for MSE
                                                measurements
  ``ETHTOOL_A_MSE_CHANNEL_A``           nested  snapshot for Channel A
  ``ETHTOOL_A_MSE_CHANNEL_B``           nested  snapshot for Channel B
  ``ETHTOOL_A_MSE_CHANNEL_C``           nested  snapshot for Channel C
  ``ETHTOOL_A_MSE_CHANNEL_D``           nested  snapshot for Channel D
  ``ETHTOOL_A_MSE_WORST_CHANNEL``       nested  snapshot for worst channel
  ``ETHTOOL_A_MSE_LINK``                nested  snapshot for link-wide aggregate
  ====================================  ======  ================================

MSE Capabilities
----------------

This nested attribute reports the capability / scaling properties used to
interpret snapshot values.

  ============================================== ======  =========================
  ``ETHTOOL_A_MSE_CAPABILITIES_MAX_AVERAGE_MSE`` uint    max avg_mse scale
  ``ETHTOOL_A_MSE_CAPABILITIES_MAX_PEAK_MSE``    uint    max peak_mse scale
  ``ETHTOOL_A_MSE_CAPABILITIES_REFRESH_RATE_PS`` uint    sample rate (picoseconds)
  ``ETHTOOL_A_MSE_CAPABILITIES_NUM_SYMBOLS``     uint    symbols per HW sample
  ============================================== ======  =========================

The max-average/peak fields are included only if the corresponding metric
is supported by the PHY. Their absence indicates that the metric is not
available.

See ``struct phy_mse_capability`` kernel documentation in
``include/linux/phy.h``.

MSE Snapshot
------------

Each per-channel nest contains an atomic snapshot of MSE values for that
selector (channel A/B/C/D, worst channel, or link).

  ==========================================  ======  ===================
  ``ETHTOOL_A_MSE_SNAPSHOT_AVERAGE_MSE``      uint    average MSE value
  ``ETHTOOL_A_MSE_SNAPSHOT_PEAK_MSE``         uint    current peak MSE
  ``ETHTOOL_A_MSE_SNAPSHOT_WORST_PEAK_MSE``   uint    worst-case peak MSE
  ==========================================  ======  ===================

Within each channel nest, only the metrics supported by the PHY will be present.

See ``struct phy_mse_snapshot`` kernel documentation in
``include/linux/phy.h``.

Request translation
===================

+62 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@
#define DP83TD510E_MASTER_SLAVE_RESOL_FAIL	BIT(15)

#define DP83TD510E_MSE_DETECT			0xa85
#define DP83TD510E_MSE_MAX			U16_MAX

#define DP83TD510_SQI_MAX	7

@@ -249,6 +250,64 @@ struct dp83td510_priv {
#define DP83TD510E_ALCD_COMPLETE			BIT(15)
#define DP83TD510E_ALCD_CABLE_LENGTH			GENMASK(10, 0)

static int dp83td510_get_mse_capability(struct phy_device *phydev,
					struct phy_mse_capability *cap)
{
	/* DP83TD510E documents only a single (average) MSE register
	 * (used to derive SQI); no peak or worst-peak counters are
	 * described. Advertise only PHY_MSE_CAP_AVG.
	 */
	cap->supported_caps = PHY_MSE_CAP_AVG;
	/* 10BASE-T1L is a single-pair medium, so there are no B/C/D channels.
	 * We still advertise PHY_MSE_CAP_CHANNEL_A to indicate that the PHY
	 * can attribute the measurement to a specific pair (the only one),
	 * rather than exposing it only as a link-aggregate.
	 *
	 * Rationale:
	 *  - Keeps the ethtool MSE_GET selection logic consistent: per-channel
	 *    (A/B/C/D) is preferred over WORST/LINK, so userspace receives a
	 *    CHANNEL_A nest instead of LINK.
	 *  - Signals to tools that "per-pair" data is available (even if there's
	 *    just one pair), avoiding the impression that only aggregate values
	 *    are supported.
	 *  - Remains compatible with multi-pair PHYs and uniform UI handling.
	 *
	 * Note: WORST and other channels are not advertised on 10BASE-T1L.
	 */
	cap->supported_caps |= PHY_MSE_CHANNEL_A | PHY_MSE_CAP_LINK;
	cap->max_average_mse = DP83TD510E_MSE_MAX;

	/* The datasheet does not specify the refresh rate or symbol count,
	 * but based on similar PHYs and standards, we can assume a common
	 * value. For 10BASE-T1L, the symbol rate is 7.5 MBd. A common
	 * diagnostic interval is around 1ms.
	 * 7.5e6 symbols/sec * 0.001 sec = 7500 symbols.
	 */
	cap->refresh_rate_ps = 1000000000; /* 1 ms */
	cap->num_symbols = 7500;

	return 0;
}

static int dp83td510_get_mse_snapshot(struct phy_device *phydev,
				      enum phy_mse_channel channel,
				      struct phy_mse_snapshot *snapshot)
{
	int ret;

	if (channel != PHY_MSE_CHANNEL_LINK &&
	    channel != PHY_MSE_CHANNEL_A)
		return -EOPNOTSUPP;

	ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_MSE_DETECT);
	if (ret < 0)
		return ret;

	snapshot->average_mse = ret;

	return 0;
}

static int dp83td510_led_brightness_set(struct phy_device *phydev, u8 index,
					enum led_brightness brightness)
{
@@ -893,6 +952,9 @@ static struct phy_driver dp83td510_driver[] = {
	.get_phy_stats	= dp83td510_get_phy_stats,
	.update_stats	= dp83td510_update_stats,

	.get_mse_capability = dp83td510_get_mse_capability,
	.get_mse_snapshot = dp83td510_get_mse_snapshot,

	.led_brightness_set = dp83td510_led_brightness_set,
	.led_hw_is_supported = dp83td510_led_hw_is_supported,
	.led_hw_control_set = dp83td510_led_hw_control_set,
+102 −0
Original line number Diff line number Diff line
@@ -2325,6 +2325,106 @@ static int kszphy_get_sqi_max(struct phy_device *phydev)
	return KSZ9477_SQI_MAX;
}

static int kszphy_get_mse_capability(struct phy_device *phydev,
				     struct phy_mse_capability *cap)
{
	/* Capabilities depend on link mode:
	 * - 1000BASE-T: per-pair SQI registers exist => expose A..D
	 *   and a WORST selector.
	 * - 100BASE-TX: HW provides a single MSE/SQI reading in the "channel A"
	 *   register, but with auto MDI-X there is no MDI-X resolution bit,
	 *   so we cannot map that register to a specific wire pair reliably.
	 *   To avoid misleading per-channel data, advertise only LINK.
	 * Other speeds: no MSE exposure via this driver.
	 *
	 * Note: WORST is *not* a hardware selector on this family.
	 * We expose it because the driver computes it in software
	 * by scanning per-channel readouts (A..D) and picking the
	 * maximum average MSE.
	 */
	if (phydev->speed == SPEED_1000)
		cap->supported_caps = PHY_MSE_CAP_CHANNEL_A |
				      PHY_MSE_CAP_CHANNEL_B |
				      PHY_MSE_CAP_CHANNEL_C |
				      PHY_MSE_CAP_CHANNEL_D |
				      PHY_MSE_CAP_WORST_CHANNEL;
	else if (phydev->speed == SPEED_100)
		cap->supported_caps = PHY_MSE_CAP_LINK;
	else
		return -EOPNOTSUPP;

	cap->max_average_mse = FIELD_MAX(KSZ9477_MMD_SQI_MASK);
	cap->refresh_rate_ps = 2000000; /* 2 us */
	/* Estimated from link modulation (125 MBd per channel) and documented
	 * refresh rate of 2 us
	 */
	cap->num_symbols = 250;

	cap->supported_caps |= PHY_MSE_CAP_AVG;

	return 0;
}

static int kszphy_get_mse_snapshot(struct phy_device *phydev,
				   enum phy_mse_channel channel,
				   struct phy_mse_snapshot *snapshot)
{
	u8 num_channels;
	int ret;

	if (phydev->speed == SPEED_1000)
		num_channels = 4;
	else if (phydev->speed == SPEED_100)
		num_channels = 1;
	else
		return -EOPNOTSUPP;

	if (channel == PHY_MSE_CHANNEL_WORST) {
		u32 worst_val = 0;
		int i;

		/* WORST is implemented in software: select the maximum
		 * average MSE across the available per-channel registers.
		 * Only defined when multiple channels exist (1000BASE-T).
		 */
		if (num_channels < 2)
			return -EOPNOTSUPP;

		for (i = 0; i < num_channels; i++) {
			ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
					KSZ9477_MMD_SIGNAL_QUALITY_CHAN_A + i);
			if (ret < 0)
				return ret;

			ret = FIELD_GET(KSZ9477_MMD_SQI_MASK, ret);
			if (ret > worst_val)
				worst_val = ret;
		}
		snapshot->average_mse = worst_val;
	} else if (channel == PHY_MSE_CHANNEL_LINK && num_channels == 1) {
		ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
				   KSZ9477_MMD_SIGNAL_QUALITY_CHAN_A);
		if (ret < 0)
			return ret;
		snapshot->average_mse = FIELD_GET(KSZ9477_MMD_SQI_MASK, ret);
	} else if (channel >= PHY_MSE_CHANNEL_A &&
		   channel <= PHY_MSE_CHANNEL_D) {
		/* Per-channel readouts are valid only for 1000BASE-T. */
		if (phydev->speed != SPEED_1000)
			return -EOPNOTSUPP;

		ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
				   KSZ9477_MMD_SIGNAL_QUALITY_CHAN_A + channel);
		if (ret < 0)
			return ret;
		snapshot->average_mse = FIELD_GET(KSZ9477_MMD_SQI_MASK, ret);
	} else {
		return -EOPNOTSUPP;
	}

	return 0;
}

static void kszphy_enable_clk(struct phy_device *phydev)
{
	struct kszphy_priv *priv = phydev->priv;
@@ -6497,6 +6597,8 @@ static struct phy_driver ksphy_driver[] = {
	.cable_test_get_status	= ksz9x31_cable_test_get_status,
	.get_sqi	= kszphy_get_sqi,
	.get_sqi_max	= kszphy_get_sqi_max,
	.get_mse_capability = kszphy_get_mse_capability,
	.get_mse_snapshot = kszphy_get_mse_snapshot,
} };

module_phy_driver(ksphy_driver);
+206 −0
Original line number Diff line number Diff line
@@ -903,6 +903,165 @@ struct phy_led {

#define to_phy_led(d) container_of(d, struct phy_led, led_cdev)

/*
 * PHY_MSE_CAP_* - Bitmask flags for Mean Square Error (MSE) capabilities
 *
 * These flags describe which MSE metrics and selectors are implemented
 * by the PHY for the current link mode. They are used in
 * struct phy_mse_capability.supported_caps.
 *
 * Standardization:
 *   The OPEN Alliance (OA) defines the presence of MSE/SQI/pMSE but not their
 *   numeric scaling, update intervals, or aggregation windows.  See:
 *     OA 100BASE-T1 TC1 v1.0, sections 6.1.1-6.1.3
 *     OA 1000BASE-T1 TC12 v2.2, sections 6.1.1-6.1.2
 *
 * Description of flags:
 *
 *   PHY_MSE_CAP_CHANNEL_A
 *     Per-pair diagnostics for Channel A are supported.  Mapping to the
 *     physical wire pair may depend on MDI/MDI-X polarity.
 *
 *   PHY_MSE_CAP_CHANNEL_B, _C, _D
 *     Same as above for channels B-D.
 *
 *   PHY_MSE_CAP_WORST_CHANNEL
 *     The PHY or driver can identify and report the single worst-performing
 *     channel without querying each one individually.
 *
 *   PHY_MSE_CAP_LINK
 *     The PHY provides only a link-wide aggregate measurement or cannot map
 *     results to a specific pair (for example 100BASE-TX with unknown
 *     MDI/MDI-X).
 *
 *   PHY_MSE_CAP_AVG
 *     Average MSE (mean DCQ metric) is supported.  For 100/1000BASE-T1 the OA
 *     recommends 2^16 symbols, scaled 0..511, but the exact scaling is
 *     vendor-specific.
 *
 *   PHY_MSE_CAP_PEAK
 *     Peak MSE (current peak within the measurement window) is supported.
 *     Defined as pMSE for 100BASE-T1; vendor-specific for others.
 *
 *   PHY_MSE_CAP_WORST_PEAK
 *     Latched worst-case peak MSE since the last read (read-to-clear if
 *     implemented).  Optional in OA 100BASE-T1 TC1 6.1.3.
 */
#define PHY_MSE_CAP_CHANNEL_A BIT(0)
#define PHY_MSE_CAP_CHANNEL_B BIT(1)
#define PHY_MSE_CAP_CHANNEL_C BIT(2)
#define PHY_MSE_CAP_CHANNEL_D BIT(3)
#define PHY_MSE_CAP_WORST_CHANNEL BIT(4)
#define PHY_MSE_CAP_LINK BIT(5)
#define PHY_MSE_CAP_AVG BIT(6)
#define PHY_MSE_CAP_PEAK BIT(7)
#define PHY_MSE_CAP_WORST_PEAK BIT(8)

/*
 * enum phy_mse_channel - Identifiers for selecting MSE measurement channels
 *
 * PHY_MSE_CHANNEL_A - PHY_MSE_CHANNEL_D
 *   Select per-pair measurement for the corresponding channel.
 *
 * PHY_MSE_CHANNEL_WORST
 *   Select the single worst-performing channel reported by hardware.
 *
 * PHY_MSE_CHANNEL_LINK
 *   Select link-wide aggregate data (used when per-pair results are
 *   unavailable).
 */
enum phy_mse_channel {
	PHY_MSE_CHANNEL_A,
	PHY_MSE_CHANNEL_B,
	PHY_MSE_CHANNEL_C,
	PHY_MSE_CHANNEL_D,
	PHY_MSE_CHANNEL_WORST,
	PHY_MSE_CHANNEL_LINK,
};

/**
 * struct phy_mse_capability - Capabilities of Mean Square Error (MSE)
 *                             measurement interface
 *
 * Standardization notes:
 *
 * - Presence of MSE/SQI/pMSE is defined by OPEN Alliance specs, but numeric
 *   scaling, refresh/update rate and aggregation windows are not fixed and
 *   are vendor-/product-specific. (OA 100BASE-T1 TC1 v1.0 6.1.*;
 *   OA 1000BASE-T1 TC12 v2.2 6.1.*)
 *
 * - Typical recommendations: 2^16 symbols and 0..511 scaling for MSE; pMSE only
 *   defined for 100BASE-T1 (sliding window example), others are vendor
 *   extensions. Drivers must report actual scale/limits here.
 *
 * Describes the MSE measurement capabilities for the current link mode. These
 * properties are dynamic and may change when link settings are modified.
 * Callers should re-query this capability after any link state change to
 * ensure they have the most up-to-date information.
 *
 * Callers should only request measurements for channels and types that are
 * indicated as supported by the @supported_caps bitmask. If @supported_caps
 * is 0, the device provides no MSE diagnostics, and driver operations should
 * typically return -EOPNOTSUPP.
 *
 * Snapshot values for average and peak MSE can be normalized to a 0..1 ratio
 * by dividing the raw snapshot by the corresponding @max_average_mse or
 * @max_peak_mse value.
 *
 * @max_average_mse: The maximum value for an average MSE snapshot. This
 *   defines the scale for the measurement. If the PHY_MSE_CAP_AVG capability is
 *   supported, this value MUST be greater than 0. (vendor-specific units).
 * @max_peak_mse: The maximum value for a peak MSE snapshot. If either
 *   PHY_MSE_CAP_PEAK or PHY_MSE_CAP_WORST_PEAK is supported, this value MUST
 *   be greater than 0. (vendor-specific units).
 * @refresh_rate_ps: The typical interval, in picoseconds, between hardware
 *   updates of the MSE values. This is an estimate, and callers should not
 *   assume synchronous sampling. (vendor-specific units).
 * @num_symbols: The number of symbols aggregated per hardware sample to
 *   calculate the MSE. (vendor-specific units).
 * @supported_caps: A bitmask of PHY_MSE_CAP_* values indicating which
 *   measurement types (e.g., average, peak) and channels
 *   (e.g., per-pair or link-wide) are supported.
 */
struct phy_mse_capability {
	u64 max_average_mse;
	u64 max_peak_mse;
	u64 refresh_rate_ps;
	u64 num_symbols;
	u32 supported_caps;
};

/**
 * struct phy_mse_snapshot - A snapshot of Mean Square Error (MSE) diagnostics
 *
 * Holds a set of MSE diagnostic values that were all captured from a single
 * measurement window.
 *
 * Values are raw, device-scaled and not normalized. Use struct
 * phy_mse_capability to interpret the scale and sampling window.
 *
 * @average_mse: The average MSE value over the measurement window.
 *   OPEN Alliance references MSE as a DCQ metric; recommends 2^16 symbols and
 *   0..511 scaling. Exact scale and refresh are vendor-specific.
 *   (100BASE-T1 TC1 v1.0 6.1.1; 1000BASE-T1 TC12 v2.2 6.1.1).
 *
 * @peak_mse: The peak MSE value observed within the measurement window.
 *   For 100BASE-T1, "pMSE" is optional and may be implemented via a sliding
 *   128-symbol window with periodic capture; not standardized for 1000BASE-T1.
 *   (100BASE-T1 TC1 v1.0 6.1.3, Table "DCQ.peakMSE").
 *
 * @worst_peak_mse: A latched high-water mark of the peak MSE since last read
 *   (read-to-clear if implemented). OPEN Alliance shows a latched "worst case
 *   peak MSE" for 100BASE-T1 pMSE; availability/semantics outside that are
 *   vendor-specific. (100BASE-T1 TC1 v1.0 6.1.3, DCQ.peakMSE high byte;
 *   1000BASE-T1 TC12 v2.2 treats DCQ details as vendor-specific.)
 */
struct phy_mse_snapshot {
	u64 average_mse;
	u64 peak_mse;
	u64 worst_peak_mse;
};

/**
 * struct phy_driver - Driver structure for a particular PHY type
 *
@@ -1184,6 +1343,53 @@ struct phy_driver {
	/** @get_sqi_max: Get the maximum signal quality indication */
	int (*get_sqi_max)(struct phy_device *dev);

	/**
	 * @get_mse_capability: Get capabilities and scale of MSE measurement
	 * @dev:    PHY device
	 * @cap: Output (filled on success)
	 *
	 * Fill @cap with the PHY's MSE capability for the current
	 * link mode: scale limits (max_average_mse, max_peak_mse), update
	 * interval (refresh_rate_ps), sample length (num_symbols) and the
	 * capability bitmask (supported_caps).
	 *
	 * Implementations may defer capability report until hardware has
	 * converged; in that case they should return -EAGAIN and allow the
	 * caller to retry later.
	 *
	 * Return: 0 on success. On failure, returns a negative errno code, such
	 * as -EOPNOTSUPP if MSE measurement is not supported by the PHY or in
	 * the current link mode, or -EAGAIN if the capability information is
	 * not yet available.
	 */
	int (*get_mse_capability)(struct phy_device *dev,
				  struct phy_mse_capability *cap);

	/**
	 * @get_mse_snapshot: Retrieve a snapshot of MSE diagnostic values
	 * @dev:      PHY device
	 * @channel:  Channel identifier (PHY_MSE_CHANNEL_*)
	 * @snapshot: Output (filled on success)
	 *
	 * Fill @snapshot with a correlated set of MSE values from the most
	 * recent measurement window.
	 *
	 * Callers must validate @channel against supported_caps returned by
	 * get_mse_capability(). Drivers must not coerce @channel; if the
	 * requested selector is not implemented by the device or current link
	 * mode, the operation must fail.
	 *
	 * worst_peak_mse is latched and must be treated as read-to-clear.
	 *
	 * Return: 0 on success. On failure, returns a negative errno code, such
	 * as -EOPNOTSUPP if MSE measurement is not supported by the PHY or in
	 * the current link mode, or -EAGAIN if measurements are not yet
	 * available.
	 */
	int (*get_mse_snapshot)(struct phy_device *dev,
				enum phy_mse_channel channel,
				struct phy_mse_snapshot *snapshot);

	/* PLCA RS interface */
	/** @get_plca_cfg: Return the current PLCA configuration */
	int (*get_plca_cfg)(struct phy_device *dev,
Loading