[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250915091149.3539162-1-horatiu.vultur@microchip.com>
Date: Mon, 15 Sep 2025 11:11:49 +0200
From: Horatiu Vultur <horatiu.vultur@...rochip.com>
To: <andrew@...n.ch>, <hkallweit1@...il.com>, <linux@...linux.org.uk>,
<davem@...emloft.net>, <edumazet@...gle.com>, <kuba@...nel.org>,
<pabeni@...hat.com>
CC: <netdev@...r.kernel.org>, <linux-kernel@...r.kernel.org>, Horatiu Vultur
<horatiu.vultur@...rochip.com>
Subject: [PATCH net-next] net: phy: micrel: Add Fast link failure support for lan8842
Add support for fast link failure for lan8842, when this is enabled the
PHY will detect link down immediately (~1ms). The disadvantage of this
is that also small instability might be reported as link down.
Therefore add this feature as a tunable configuration and the user will
know when to enable or not. By default it is not enabled.
Signed-off-by: Horatiu Vultur <horatiu.vultur@...rochip.com>
---
drivers/net/phy/micrel.c | 77 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 75 insertions(+), 2 deletions(-)
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index e403cbbcead5b..a946c34dbbf79 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -107,6 +107,7 @@
#define LAN8814_INTC 0x18
#define LAN8814_INTS 0x1B
+#define LAN8814_INT_FLF BIT(15)
#define LAN8814_INT_LINK_DOWN BIT(2)
#define LAN8814_INT_LINK_UP BIT(0)
#define LAN8814_INT_LINK (LAN8814_INT_LINK_UP |\
@@ -2805,6 +2806,14 @@ static int ksz886x_cable_test_get_status(struct phy_device *phydev,
return ret;
}
+/**
+ * LAN8814_PAGE_PCS - Selects Extended Page 0.
+ *
+ * This page appaers to control the fast link failure and there are different
+ * debug info registers.
+ */
+#define LAN8814_PAGE_PCS 0
+
/**
* LAN8814_PAGE_AFE_PMA - Selects Extended Page 1.
*
@@ -5910,7 +5919,8 @@ static int lan8842_config_intr(struct phy_device *phydev)
if (err)
return err;
- err = phy_write(phydev, LAN8814_INTC, LAN8814_INT_LINK);
+ err = phy_write(phydev, LAN8814_INTC,
+ LAN8814_INT_LINK | LAN8814_INT_FLF);
} else {
err = phy_write(phydev, LAN8814_INTC, 0);
if (err)
@@ -5986,7 +5996,7 @@ static irqreturn_t lan8842_handle_interrupt(struct phy_device *phydev)
return IRQ_NONE;
}
- if (irq_status & LAN8814_INT_LINK) {
+ if (irq_status & (LAN8814_INT_LINK | LAN8814_INT_FLF)) {
phy_trigger_machine(phydev);
ret = IRQ_HANDLED;
}
@@ -6055,6 +6065,67 @@ static int lan8842_update_stats(struct phy_device *phydev)
return 0;
}
+#define LAN8842_FLF 15 /* 0x0e */
+#define LAN8842_FLF_ENA BIT(1)
+#define LAN8842_FLF_ENA_LINK_DOWN BIT(0)
+
+static int lan8842_get_fast_down(struct phy_device *phydev, u8 *msecs)
+{
+ int ret;
+
+ ret = lanphy_read_page_reg(phydev, LAN8814_PAGE_PCS, LAN8842_FLF);
+ if (ret < 0)
+ return ret;
+
+ if (ret & LAN8842_FLF_ENA)
+ *msecs = ETHTOOL_PHY_FAST_LINK_DOWN_ON;
+ else
+ *msecs = ETHTOOL_PHY_FAST_LINK_DOWN_OFF;
+
+ return 0;
+}
+
+static int lan8842_set_fast_down(struct phy_device *phydev, const u8 *msecs)
+{
+ if (*msecs == ETHTOOL_PHY_FAST_LINK_DOWN_ON)
+ return lanphy_modify_page_reg(phydev, LAN8814_PAGE_PCS,
+ LAN8842_FLF,
+ LAN8842_FLF_ENA |
+ LAN8842_FLF_ENA_LINK_DOWN,
+ LAN8842_FLF_ENA |
+ LAN8842_FLF_ENA_LINK_DOWN);
+
+ if (*msecs == ETHTOOL_PHY_FAST_LINK_DOWN_OFF)
+ return lanphy_modify_page_reg(phydev, LAN8814_PAGE_PCS,
+ LAN8842_FLF,
+ LAN8842_FLF_ENA |
+ LAN8842_FLF_ENA_LINK_DOWN, 0);
+
+ return -EINVAL;
+}
+
+static int lan8842_get_tunable(struct phy_device *phydev,
+ struct ethtool_tunable *tuna, void *data)
+{
+ switch (tuna->id) {
+ case ETHTOOL_PHY_FAST_LINK_DOWN:
+ return lan8842_get_fast_down(phydev, data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int lan8842_set_tunable(struct phy_device *phydev,
+ struct ethtool_tunable *tuna, const void *data)
+{
+ switch (tuna->id) {
+ case ETHTOOL_PHY_FAST_LINK_DOWN:
+ return lan8842_set_fast_down(phydev, data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static void lan8842_get_phy_stats(struct phy_device *phydev,
struct ethtool_eth_phy_stats *eth_stats,
struct ethtool_phy_stats *stats)
@@ -6299,6 +6370,8 @@ static struct phy_driver ksphy_driver[] = {
.handle_interrupt = lan8842_handle_interrupt,
.get_phy_stats = lan8842_get_phy_stats,
.update_stats = lan8842_update_stats,
+ .get_tunable = lan8842_get_tunable,
+ .set_tunable = lan8842_set_tunable,
.cable_test_start = lan8814_cable_test_start,
.cable_test_get_status = ksz886x_cable_test_get_status,
}, {
--
2.34.1
Powered by blists - more mailing lists