This RFC patch is a follow-up to discussion [0]. In cases like missing PHY firmware we may want to keep the PHY from being brought up, but still allow MDIO access. Setting state PERM_FAIL in the probe or config_init callback allows to achieve this.
[0] https://marc.info/?t=155973142200002&r=1&w=2 Signed-off-by: Heiner Kallweit <hkallwe...@gmail.com> --- drivers/net/phy/phy.c | 10 ++++++++-- include/linux/phy.h | 5 +++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index d91507650..889437512 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -44,6 +44,7 @@ static const char *phy_state_to_str(enum phy_state st) PHY_STATE_STR(RUNNING) PHY_STATE_STR(NOLINK) PHY_STATE_STR(HALTED) + PHY_STATE_STR(PERM_FAIL) } return NULL; @@ -744,7 +745,8 @@ static void phy_error(struct phy_device *phydev) WARN_ON(1); mutex_lock(&phydev->lock); - phydev->state = PHY_HALTED; + if (phydev->state != PHY_PERM_FAIL) + phydev->state = PHY_HALTED; mutex_unlock(&phydev->lock); phy_trigger_machine(phydev); @@ -897,7 +899,10 @@ void phy_start(struct phy_device *phydev) { mutex_lock(&phydev->lock); - if (phydev->state != PHY_READY && phydev->state != PHY_HALTED) { + if (phydev->state == PHY_PERM_FAIL) { + phydev_warn(phydev, "Can't start PHY because it's in state PERM_FAIL\n"); + goto out; + } else if (phydev->state != PHY_READY && phydev->state != PHY_HALTED) { WARN(1, "called from state %s\n", phy_state_to_str(phydev->state)); goto out; @@ -934,6 +939,7 @@ void phy_state_machine(struct work_struct *work) switch (phydev->state) { case PHY_DOWN: case PHY_READY: + case PHY_PERM_FAIL: break; case PHY_UP: needs_aneg = true; diff --git a/include/linux/phy.h b/include/linux/phy.h index d0af7d37f..7f47b6605 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -300,11 +300,16 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr); * HALTED: PHY is up, but no polling or interrupts are done. Or * PHY is in an error state. * - phy_start moves to UP + * + * PERM_FAIL: A permanent failure was detected and PHY isn't allowed to be + * brought up. Still we don't want to fail in probe to allow MDIO access + * to the PHY, e.g. to load missing firmware. */ enum phy_state { PHY_DOWN = 0, PHY_READY, PHY_HALTED, + PHY_PERM_FAIL, PHY_UP, PHY_RUNNING, PHY_NOLINK, -- 2.21.0