* [PATCH net-next v3 1/1] phy: micrel: add Signal Quality Indicator (SQI) support for KSZ9477 switch PHYs
@ 2025-06-27 11:25 Oleksij Rempel
2025-06-27 15:45 ` Oleksij Rempel
2025-07-02 2:40 ` patchwork-bot+netdevbpf
0 siblings, 2 replies; 3+ messages in thread
From: Oleksij Rempel @ 2025-06-27 11:25 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Oleksij Rempel, kernel, linux-kernel, Russell King, netdev
Add support for the Signal Quality Indicator (SQI) feature on KSZ9477
family switches, providing a relative measure of receive signal quality.
The hardware exposes separate SQI readings per channel. For 1000BASE-T,
all four channels are read. For 100BASE-TX, only one channel is reported,
but which receive pair is active depends on Auto MDI-X negotiation, which
is not exposed by the hardware. Therefore, it is not possible to reliably
map the measured channel to a specific wire pair.
This resolves an earlier discussion about how to handle multi-channel
SQI. Originally, the plan was to expose all channels individually.
However, since pair mapping is sometimes unavailable, this
implementation treats SQI as a per-link metric instead. This fallback
avoids ambiguity and ensures consistent behavior. The existing get_sqi()
UAPI was designed for single-pair Ethernet (SPE), where per-pair and
per-link are effectively equivalent. Restricting its use to per-link
metrics does not introduce regressions for existing users.
The raw 7-bit SQI value (0–127, lower is better) is converted to the
standard 0–7 (high is better) scale. Empirical testing showed that the
link becomes unstable around a raw value of 8.
The SQI raw value remains zero if no data is received, even if noise is
present. This confirms that the measurement reflects the "quality" during
active data reception rather than the passive line state. User space
must ensure that traffic is present on the link to obtain valid SQI
readings.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
changes v3:
- Update commit message
- drop usleep
- bring back multi channel support
changes v2:
- Reword commit message
- Fix SQI value inversion
- Implement an empirically-derived, non-linear mapping to the standard
0-7 SQI scale
---
drivers/net/phy/micrel.c | 132 +++++++++++++++++++++++++++++++++++++++
1 file changed, 132 insertions(+)
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index d0429dc8f561..74fd6ff32c6c 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -2173,6 +2173,136 @@ static void kszphy_get_phy_stats(struct phy_device *phydev,
stats->rx_errors = priv->phy_stats.rx_err_pkt_cnt;
}
+/* Base register for Signal Quality Indicator (SQI) - Channel A
+ *
+ * MMD Address: MDIO_MMD_PMAPMD (0x01)
+ * Register: 0xAC (Channel A)
+ * Each channel (pair) has its own register:
+ * Channel A: 0xAC
+ * Channel B: 0xAD
+ * Channel C: 0xAE
+ * Channel D: 0xAF
+ */
+#define KSZ9477_MMD_SIGNAL_QUALITY_CHAN_A 0xac
+
+/* SQI field mask for bits [14:8]
+ *
+ * SQI indicates relative quality of the signal.
+ * A lower value indicates better signal quality.
+ */
+#define KSZ9477_MMD_SQI_MASK GENMASK(14, 8)
+
+#define KSZ9477_MAX_CHANNELS 4
+#define KSZ9477_SQI_MAX 7
+
+/* Number of SQI samples to average for a stable result.
+ *
+ * Reference: KSZ9477S Datasheet DS00002392C, Section 4.1.11 (page 26)
+ * For noisy environments, a minimum of 30–50 readings is recommended.
+ */
+#define KSZ9477_SQI_SAMPLE_COUNT 40
+
+/* The hardware SQI register provides a raw value from 0-127, where a lower
+ * value indicates better signal quality. However, empirical testing has
+ * shown that only the 0-7 range is relevant for a functional link. A raw
+ * value of 8 or higher was measured directly before link drop. This aligns
+ * with the OPEN Alliance recommendation that SQI=0 should represent the
+ * pre-failure state.
+ *
+ * This table provides a non-linear mapping from the useful raw hardware
+ * values (0-7) to the standard 0-7 SQI scale, where higher is better.
+ */
+static const u8 ksz_sqi_mapping[] = {
+ 7, /* raw 0 -> SQI 7 */
+ 7, /* raw 1 -> SQI 7 */
+ 6, /* raw 2 -> SQI 6 */
+ 5, /* raw 3 -> SQI 5 */
+ 4, /* raw 4 -> SQI 4 */
+ 3, /* raw 5 -> SQI 3 */
+ 2, /* raw 6 -> SQI 2 */
+ 1, /* raw 7 -> SQI 1 */
+};
+
+/**
+ * kszphy_get_sqi - Read, average, and map Signal Quality Index (SQI)
+ * @phydev: the PHY device
+ *
+ * This function reads and processes the raw Signal Quality Index from the
+ * PHY. Based on empirical testing, a raw value of 8 or higher indicates a
+ * pre-failure state and is mapped to SQI 0. Raw values from 0-7 are
+ * mapped to the standard 0-7 SQI scale via a lookup table.
+ *
+ * Return: SQI value (0–7), or a negative errno on failure.
+ */
+static int kszphy_get_sqi(struct phy_device *phydev)
+{
+ int sum[KSZ9477_MAX_CHANNELS] = { 0 };
+ int worst_sqi = KSZ9477_SQI_MAX;
+ int i, val, raw_sqi, ch;
+ u8 channels;
+
+ /* Determine applicable channels based on link speed */
+ if (phydev->speed == SPEED_1000)
+ channels = 4;
+ else if (phydev->speed == SPEED_100)
+ channels = 1;
+ else
+ return -EOPNOTSUPP;
+
+ /* Sample and accumulate SQI readings for each pair (currently only one).
+ *
+ * Reference: KSZ9477S Datasheet DS00002392C, Section 4.1.11 (page 26)
+ * - The SQI register is updated every 2 µs.
+ * - Values may fluctuate significantly, even in low-noise environments.
+ * - For reliable estimation, average a minimum of 30–50 samples
+ * (recommended for noisy environments)
+ * - In noisy environments, individual readings are highly unreliable.
+ *
+ * We use 40 samples per pair with a delay of 3 µs between each
+ * read to ensure new values are captured (2 µs update interval).
+ */
+ for (i = 0; i < KSZ9477_SQI_SAMPLE_COUNT; i++) {
+ for (ch = 0; ch < channels; ch++) {
+ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
+ KSZ9477_MMD_SIGNAL_QUALITY_CHAN_A + ch);
+ if (val < 0)
+ return val;
+
+ raw_sqi = FIELD_GET(KSZ9477_MMD_SQI_MASK, val);
+ sum[ch] += raw_sqi;
+
+ /* We communicate with the PHY via MDIO via SPI or
+ * I2C, which is relatively slow. At least slower than
+ * the update interval of the SQI register.
+ * So, we can skip the delay between reads.
+ */
+ }
+ }
+
+ /* Calculate average for each channel and find the worst SQI */
+ for (ch = 0; ch < channels; ch++) {
+ int avg_raw_sqi = sum[ch] / KSZ9477_SQI_SAMPLE_COUNT;
+ int mapped_sqi;
+
+ /* Handle the pre-fail/failed state first. */
+ if (avg_raw_sqi >= ARRAY_SIZE(ksz_sqi_mapping))
+ mapped_sqi = 0;
+ else
+ /* Use the lookup table for the good signal range. */
+ mapped_sqi = ksz_sqi_mapping[avg_raw_sqi];
+
+ if (mapped_sqi < worst_sqi)
+ worst_sqi = mapped_sqi;
+ }
+
+ return worst_sqi;
+}
+
+static int kszphy_get_sqi_max(struct phy_device *phydev)
+{
+ return KSZ9477_SQI_MAX;
+}
+
static void kszphy_enable_clk(struct phy_device *phydev)
{
struct kszphy_priv *priv = phydev->priv;
@@ -5801,6 +5931,8 @@ static struct phy_driver ksphy_driver[] = {
.update_stats = kszphy_update_stats,
.cable_test_start = ksz9x31_cable_test_start,
.cable_test_get_status = ksz9x31_cable_test_get_status,
+ .get_sqi = kszphy_get_sqi,
+ .get_sqi_max = kszphy_get_sqi_max,
} };
module_phy_driver(ksphy_driver);
--
2.39.5
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH net-next v3 1/1] phy: micrel: add Signal Quality Indicator (SQI) support for KSZ9477 switch PHYs
2025-06-27 11:25 [PATCH net-next v3 1/1] phy: micrel: add Signal Quality Indicator (SQI) support for KSZ9477 switch PHYs Oleksij Rempel
@ 2025-06-27 15:45 ` Oleksij Rempel
2025-07-02 2:40 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: Oleksij Rempel @ 2025-06-27 15:45 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: kernel, linux-kernel, Russell King, netdev
On Fri, Jun 27, 2025 at 01:25:39PM +0200, Oleksij Rempel wrote:
> Add support for the Signal Quality Indicator (SQI) feature on KSZ9477
> family switches, providing a relative measure of receive signal quality.
>
> The hardware exposes separate SQI readings per channel. For 1000BASE-T,
> all four channels are read. For 100BASE-TX, only one channel is reported,
> but which receive pair is active depends on Auto MDI-X negotiation, which
> is not exposed by the hardware. Therefore, it is not possible to reliably
> map the measured channel to a specific wire pair.
>
> This resolves an earlier discussion about how to handle multi-channel
> SQI. Originally, the plan was to expose all channels individually.
> However, since pair mapping is sometimes unavailable, this
> implementation treats SQI as a per-link metric instead. This fallback
> avoids ambiguity and ensures consistent behavior. The existing get_sqi()
> UAPI was designed for single-pair Ethernet (SPE), where per-pair and
> per-link are effectively equivalent. Restricting its use to per-link
> metrics does not introduce regressions for existing users.
>
> The raw 7-bit SQI value (0–127, lower is better) is converted to the
> standard 0–7 (high is better) scale. Empirical testing showed that the
> link becomes unstable around a raw value of 8.
>
> The SQI raw value remains zero if no data is received, even if noise is
> present. This confirms that the measurement reflects the "quality" during
> active data reception rather than the passive line state. User space
> must ensure that traffic is present on the link to obtain valid SQI
> readings.
Update for this statement: it is valid only if EEE is active. With
disabled EEE, SQI provide correct value even if no data is transferred.
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net-next v3 1/1] phy: micrel: add Signal Quality Indicator (SQI) support for KSZ9477 switch PHYs
2025-06-27 11:25 [PATCH net-next v3 1/1] phy: micrel: add Signal Quality Indicator (SQI) support for KSZ9477 switch PHYs Oleksij Rempel
2025-06-27 15:45 ` Oleksij Rempel
@ 2025-07-02 2:40 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-07-02 2:40 UTC (permalink / raw)
To: Oleksij Rempel
Cc: andrew, hkallweit1, davem, edumazet, kuba, pabeni, kernel,
linux-kernel, linux, netdev
Hello:
This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Fri, 27 Jun 2025 13:25:39 +0200 you wrote:
> Add support for the Signal Quality Indicator (SQI) feature on KSZ9477
> family switches, providing a relative measure of receive signal quality.
>
> The hardware exposes separate SQI readings per channel. For 1000BASE-T,
> all four channels are read. For 100BASE-TX, only one channel is reported,
> but which receive pair is active depends on Auto MDI-X negotiation, which
> is not exposed by the hardware. Therefore, it is not possible to reliably
> map the measured channel to a specific wire pair.
>
> [...]
Here is the summary with links:
- [net-next,v3,1/1] phy: micrel: add Signal Quality Indicator (SQI) support for KSZ9477 switch PHYs
https://git.kernel.org/netdev/net-next/c/f461c7a885d9
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-07-02 2:40 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-27 11:25 [PATCH net-next v3 1/1] phy: micrel: add Signal Quality Indicator (SQI) support for KSZ9477 switch PHYs Oleksij Rempel
2025-06-27 15:45 ` Oleksij Rempel
2025-07-02 2:40 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).