aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/sfp.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2019-12-11 10:56:09 +0000
committerDavid S. Miller <davem@davemloft.net>2019-12-11 11:53:41 -0800
commit74c551ca5a0edcc9cf66a3b73fd95b9a8615bfd0 (patch)
tree8d40d72ad4c72c8a37a998fb27085363f5b6b967 /drivers/net/phy/sfp.c
parentnet: sfp: add more extended compliance codes (diff)
downloadlinux-dev-74c551ca5a0edcc9cf66a3b73fd95b9a8615bfd0.tar.xz
linux-dev-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.c8
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 */