diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2019-12-11 10:56:09 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-12-11 11:53:41 -0800 |
commit | 74c551ca5a0edcc9cf66a3b73fd95b9a8615bfd0 (patch) | |
tree | 8d40d72ad4c72c8a37a998fb27085363f5b6b967 /drivers/net/phy/sfp.c | |
parent | 0fbd26a9fb6875b98fcfff523831fec47bc5e9a2 (diff) | |
download | linux-stable-74c551ca5a0edcc9cf66a3b73fd95b9a8615bfd0.tar.gz linux-stable-74c551ca5a0edcc9cf66a3b73fd95b9a8615bfd0.tar.bz2 linux-stable-74c551ca5a0edcc9cf66a3b73fd95b9a8615bfd0.zip |
net: sfp: add module start/stop upstream notifications
When dealing with some copper modules, we can't positively know the
module capabilities are until we have probed the PHY. Without the full
capabilities, we may end up failing a module that we could otherwise
drive with a restricted set of capabilities.
An example of this would be a module with a NBASE-T PHY plugged into
a host that supports phy interface modes 2500BASE-X and SGMII. The
PHY supports 10GBASE-R, 5000BASE-X, 2500BASE-X, SGMII interface modes,
which means a subset of the capabilities are compatible with the host.
However, reading the module EEPROM leads us to believe that the module
only supports ethtool link mode 10GBASE-T, which is incompatible with
the host - and thus results in the module being rejected.
This patch adds an extra notification which are triggered after the
SFP module's PHY probe, and a corresponding notification just before
the PHY is removed.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy/sfp.c')
-rw-r--r-- | drivers/net/phy/sfp.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index ad3808307dba..23f30dac0f17 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -59,6 +59,7 @@ enum { SFP_DEV_UP, SFP_S_DOWN = 0, + SFP_S_FAIL, SFP_S_WAIT, SFP_S_INIT, SFP_S_INIT_TX_FAULT, @@ -122,6 +123,7 @@ static const char *event_to_str(unsigned short event) static const char * const sm_state_strings[] = { [SFP_S_DOWN] = "down", + [SFP_S_FAIL] = "fail", [SFP_S_WAIT] = "wait", [SFP_S_INIT] = "init", [SFP_S_INIT_TX_FAULT] = "init_tx_fault", @@ -1826,6 +1828,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event) if (sfp->sm_state == SFP_S_LINK_UP && sfp->sm_dev_state == SFP_DEV_UP) sfp_sm_link_down(sfp); + if (sfp->sm_state > SFP_S_INIT) + sfp_module_stop(sfp->sfp_bus); if (sfp->mod_phy) sfp_sm_phy_detach(sfp); sfp_module_tx_disable(sfp); @@ -1893,6 +1897,10 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event) * clear. Probe for the PHY and check the LOS state. */ sfp_sm_probe_for_phy(sfp); + if (sfp_module_start(sfp->sfp_bus)) { + sfp_sm_next(sfp, SFP_S_FAIL, 0); + break; + } sfp_sm_link_check_los(sfp); /* Reset the fault retry count */ |