Some PHYs have malfunctionning isolation modes, where the MII lines
aren't correctly set in high-impedance, potentially interfering with the
MII bus in unexpected ways. Some other PHYs simply don't support it.
The isolation support may depend on the interface mode being used, so
introduce a new driver callback to report the isolation support in the
current PHY configuration.
As some PHYs just never support isolation, introduce a genphy helper
that can be used for strictly non-isolating PHYs.
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
V2 : Moved from flag to callback, introduced genphy helper
drivers/net/phy/phy_device.c | 11 +++++++++++
include/linux/phy.h | 19 +++++++++++++++++++
2 files changed, 30 insertions(+)
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index a0d8ff995024..9294b73c391a 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -2127,6 +2127,14 @@ int phy_loopback(struct phy_device *phydev, bool enable)
}
EXPORT_SYMBOL(phy_loopback);
+static bool phy_can_isolate(struct phy_device *phydev)
+{
+ if (phydev->drv && phydev->drv->can_isolate)
+ return phydev->drv->can_isolate(phydev);
+
+ return true;
+}
+
int phy_isolate(struct phy_device *phydev, bool enable)
{
int ret = 0;
@@ -2134,6 +2142,9 @@ int phy_isolate(struct phy_device *phydev, bool enable)
if (!phydev->drv)
return -EIO;
+ if (!phy_can_isolate(phydev))
+ return -EOPNOTSUPP;
+
mutex_lock(&phydev->lock);
if (enable && phydev->isolated) {
diff --git a/include/linux/phy.h b/include/linux/phy.h
index ae33919aa0f5..e43f7169c57d 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1192,6 +1192,19 @@ struct phy_driver {
*/
int (*led_polarity_set)(struct phy_device *dev, int index,
unsigned long modes);
+
+ /**
+ * @can_isolate: Query the PHY isolation capability
+ * @dev: PHY device to query
+ *
+ * Although PHY isolation is part of 802.3, not all PHYs support that
+ * feature. Some PHYs can only support isolation when using a specific
+ * phy_interface_mode, and some don't support it at all.
+ *
+ * Returns true if the PHY can isolate in its current configuration,
+ * false otherwise.
+ */
+ bool (*can_isolate)(struct phy_device *dev);
};
#define to_phy_driver(d) container_of_const(to_mdio_common_driver(d), \
struct phy_driver, mdiodrv)
@@ -1910,6 +1923,12 @@ static inline int genphy_no_config_intr(struct phy_device *phydev)
{
return 0;
}
+
+static inline bool genphy_no_isolate(struct phy_device *phydev)
+{
+ return false;
+}
+
int genphy_read_mmd_unsupported(struct phy_device *phdev, int devad,
u16 regnum);
int genphy_write_mmd_unsupported(struct phy_device *phdev, int devnum,
--
2.46.1