Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: phy: dp83td510: add MSE interface support for 10BASE-T1L

Implement get_mse_capability() and get_mse_snapshot() for the DP83TD510E
to expose its Mean Square Error (MSE) register via the new PHY MSE
UAPI.

The DP83TD510E does not document any peak MSE values; it only exposes
a single average MSE register used internally to derive SQI. This
implementation therefore advertises only PHY_MSE_CAP_AVG, along with
LINK and channel-A selectors. Scaling is fixed to 0xFFFF, and the
refresh interval/number of symbols are estimated from 10BASE-T1L
symbol rate (7.5 MBd) and typical diagnostic intervals (~1 ms).

For 10BASE-T1L deployments, SQI is a reliable indicator of link
modulation quality once the link is established, but it does not
indicate whether autonegotiation pulses will be correctly received
in marginal conditions. MSE provides a direct measurement of slicer
error rate that can be used to evaluate if autonegotiation is likely
to succeed under a given cable length and condition. In practice,
testing such scenarios often requires forcing a fixed-link setup to
isolate MSE behaviour from the autonegotiation process.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20251027122801.982364-5-o.rempel@pengutronix.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Oleksij Rempel and committed by
Jakub Kicinski
fd93ed77 335a9660

+62
+62
drivers/net/phy/dp83td510.c
··· 61 61 #define DP83TD510E_MASTER_SLAVE_RESOL_FAIL BIT(15) 62 62 63 63 #define DP83TD510E_MSE_DETECT 0xa85 64 + #define DP83TD510E_MSE_MAX U16_MAX 64 65 65 66 #define DP83TD510_SQI_MAX 7 66 67 ··· 249 248 #define DP83TD510E_ALCD_STAT 0xa9f 250 249 #define DP83TD510E_ALCD_COMPLETE BIT(15) 251 250 #define DP83TD510E_ALCD_CABLE_LENGTH GENMASK(10, 0) 251 + 252 + static int dp83td510_get_mse_capability(struct phy_device *phydev, 253 + struct phy_mse_capability *cap) 254 + { 255 + /* DP83TD510E documents only a single (average) MSE register 256 + * (used to derive SQI); no peak or worst-peak counters are 257 + * described. Advertise only PHY_MSE_CAP_AVG. 258 + */ 259 + cap->supported_caps = PHY_MSE_CAP_AVG; 260 + /* 10BASE-T1L is a single-pair medium, so there are no B/C/D channels. 261 + * We still advertise PHY_MSE_CAP_CHANNEL_A to indicate that the PHY 262 + * can attribute the measurement to a specific pair (the only one), 263 + * rather than exposing it only as a link-aggregate. 264 + * 265 + * Rationale: 266 + * - Keeps the ethtool MSE_GET selection logic consistent: per-channel 267 + * (A/B/C/D) is preferred over WORST/LINK, so userspace receives a 268 + * CHANNEL_A nest instead of LINK. 269 + * - Signals to tools that "per-pair" data is available (even if there's 270 + * just one pair), avoiding the impression that only aggregate values 271 + * are supported. 272 + * - Remains compatible with multi-pair PHYs and uniform UI handling. 273 + * 274 + * Note: WORST and other channels are not advertised on 10BASE-T1L. 275 + */ 276 + cap->supported_caps |= PHY_MSE_CHANNEL_A | PHY_MSE_CAP_LINK; 277 + cap->max_average_mse = DP83TD510E_MSE_MAX; 278 + 279 + /* The datasheet does not specify the refresh rate or symbol count, 280 + * but based on similar PHYs and standards, we can assume a common 281 + * value. For 10BASE-T1L, the symbol rate is 7.5 MBd. A common 282 + * diagnostic interval is around 1ms. 283 + * 7.5e6 symbols/sec * 0.001 sec = 7500 symbols. 284 + */ 285 + cap->refresh_rate_ps = 1000000000; /* 1 ms */ 286 + cap->num_symbols = 7500; 287 + 288 + return 0; 289 + } 290 + 291 + static int dp83td510_get_mse_snapshot(struct phy_device *phydev, 292 + enum phy_mse_channel channel, 293 + struct phy_mse_snapshot *snapshot) 294 + { 295 + int ret; 296 + 297 + if (channel != PHY_MSE_CHANNEL_LINK && 298 + channel != PHY_MSE_CHANNEL_A) 299 + return -EOPNOTSUPP; 300 + 301 + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_MSE_DETECT); 302 + if (ret < 0) 303 + return ret; 304 + 305 + snapshot->average_mse = ret; 306 + 307 + return 0; 308 + } 252 309 253 310 static int dp83td510_led_brightness_set(struct phy_device *phydev, u8 index, 254 311 enum led_brightness brightness) ··· 951 892 .cable_test_get_status = dp83td510_cable_test_get_status, 952 893 .get_phy_stats = dp83td510_get_phy_stats, 953 894 .update_stats = dp83td510_update_stats, 895 + 896 + .get_mse_capability = dp83td510_get_mse_capability, 897 + .get_mse_snapshot = dp83td510_get_mse_snapshot, 954 898 955 899 .led_brightness_set = dp83td510_led_brightness_set, 956 900 .led_hw_is_supported = dp83td510_led_hw_is_supported,