| From 57cbf7453551db1df619b79410d79fc418d862d5 Mon Sep 17 00:00:00 2001 |
| From: Russell King <rmk+kernel@armlinux.org.uk> |
| Date: Tue, 5 Nov 2019 13:00:45 +0000 |
| Subject: [PATCH 632/660] net: sfp: move module insert reporting out of probe |
| |
| Move the module insertion reporting out of the probe handling, but |
| after we have detected that the upstream has attached (since that is |
| whom we are reporting insertion to.) |
| |
| Only report module removal if we had previously reported a module |
| insertion. |
| |
| This gives cleaner semantics, and means we can probe the module before |
| we have an upstream attached. |
| |
| Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> |
| --- |
| drivers/net/phy/sfp.c | 58 +++++++++++++++++++++++++++++-------------- |
| 1 file changed, 40 insertions(+), 18 deletions(-) |
| |
| --- a/drivers/net/phy/sfp.c |
| +++ b/drivers/net/phy/sfp.c |
| @@ -47,11 +47,12 @@ enum { |
| SFP_E_TIMEOUT, |
| |
| SFP_MOD_EMPTY = 0, |
| + SFP_MOD_ERROR, |
| SFP_MOD_PROBE, |
| + SFP_MOD_WAITDEV, |
| SFP_MOD_HPOWER, |
| SFP_MOD_WAITPWR, |
| SFP_MOD_PRESENT, |
| - SFP_MOD_ERROR, |
| |
| SFP_DEV_DETACHED = 0, |
| SFP_DEV_DOWN, |
| @@ -70,11 +71,12 @@ enum { |
| |
| static const char * const mod_state_strings[] = { |
| [SFP_MOD_EMPTY] = "empty", |
| + [SFP_MOD_ERROR] = "error", |
| [SFP_MOD_PROBE] = "probe", |
| + [SFP_MOD_WAITDEV] = "waitdev", |
| [SFP_MOD_HPOWER] = "hpower", |
| [SFP_MOD_WAITPWR] = "waitpwr", |
| [SFP_MOD_PRESENT] = "present", |
| - [SFP_MOD_ERROR] = "error", |
| }; |
| |
| static const char *mod_state_to_str(unsigned short mod_state) |
| @@ -1544,16 +1546,13 @@ static int sfp_sm_mod_probe(struct sfp * |
| if (ret < 0) |
| return ret; |
| |
| - ret = sfp_module_insert(sfp->sfp_bus, &sfp->id); |
| - if (ret < 0) |
| - return ret; |
| - |
| return 0; |
| } |
| |
| static void sfp_sm_mod_remove(struct sfp *sfp) |
| { |
| - sfp_module_remove(sfp->sfp_bus); |
| + if (sfp->sm_mod_state > SFP_MOD_WAITDEV) |
| + sfp_module_remove(sfp->sfp_bus); |
| |
| sfp_hwmon_remove(sfp); |
| |
| @@ -1604,12 +1603,12 @@ static void sfp_sm_module(struct sfp *sf |
| } |
| |
| /* Handle device detach globally */ |
| - if (sfp->sm_dev_state < SFP_DEV_DOWN) { |
| + if (sfp->sm_dev_state < SFP_DEV_DOWN && |
| + sfp->sm_mod_state > SFP_MOD_WAITDEV) { |
| if (sfp->module_power_mW > 1000 && |
| sfp->sm_mod_state > SFP_MOD_HPOWER) |
| sfp_sm_mod_hpower(sfp, false); |
| - if (sfp->sm_mod_state > SFP_MOD_EMPTY) |
| - sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0); |
| + sfp_sm_mod_next(sfp, SFP_MOD_WAITDEV, 0); |
| return; |
| } |
| |
| @@ -1620,6 +1619,7 @@ static void sfp_sm_module(struct sfp *sf |
| break; |
| |
| case SFP_MOD_PROBE: |
| + /* Wait for T_PROBE_INIT to time out */ |
| if (event != SFP_E_TIMEOUT) |
| break; |
| |
| @@ -1633,6 +1633,20 @@ static void sfp_sm_module(struct sfp *sf |
| break; |
| } |
| |
| + sfp_sm_mod_next(sfp, SFP_MOD_WAITDEV, 0); |
| + /* fall through */ |
| + case SFP_MOD_WAITDEV: |
| + /* Ensure that the device is attached before proceeding */ |
| + if (sfp->sm_dev_state < SFP_DEV_DOWN) |
| + break; |
| + |
| + /* Report the module insertion to the upstream device */ |
| + err = sfp_module_insert(sfp->sfp_bus, &sfp->id); |
| + if (err < 0) { |
| + sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0); |
| + break; |
| + } |
| + |
| /* If this is a power level 1 module, we are done */ |
| if (sfp->module_power_mW <= 1000) |
| goto insert; |
| @@ -1642,12 +1656,17 @@ static void sfp_sm_module(struct sfp *sf |
| case SFP_MOD_HPOWER: |
| /* Enable high power mode */ |
| err = sfp_sm_mod_hpower(sfp, true); |
| - if (err == 0) |
| - sfp_sm_mod_next(sfp, SFP_MOD_WAITPWR, T_HPOWER_LEVEL); |
| - else if (err != -EAGAIN) |
| - sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0); |
| - else |
| - sfp_sm_set_timer(sfp, T_PROBE_RETRY); |
| + if (err < 0) { |
| + if (err != -EAGAIN) { |
| + sfp_module_remove(sfp->sfp_bus); |
| + sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0); |
| + } else { |
| + sfp_sm_set_timer(sfp, T_PROBE_RETRY); |
| + } |
| + break; |
| + } |
| + |
| + sfp_sm_mod_next(sfp, SFP_MOD_WAITPWR, T_HPOWER_LEVEL); |
| break; |
| |
| case SFP_MOD_WAITPWR: |
| @@ -1815,8 +1834,6 @@ static void sfp_sm_event(struct sfp *sfp |
| static void sfp_attach(struct sfp *sfp) |
| { |
| sfp_sm_event(sfp, SFP_E_DEV_ATTACH); |
| - if (sfp->state & SFP_F_PRESENT) |
| - sfp_sm_event(sfp, SFP_E_INSERT); |
| } |
| |
| static void sfp_detach(struct sfp *sfp) |
| @@ -2084,6 +2101,11 @@ static int sfp_probe(struct platform_dev |
| sfp->state |= SFP_F_RATE_SELECT; |
| sfp_set_state(sfp, sfp->state); |
| sfp_module_tx_disable(sfp); |
| + if (sfp->state & SFP_F_PRESENT) { |
| + rtnl_lock(); |
| + sfp_sm_event(sfp, SFP_E_INSERT); |
| + rtnl_unlock(); |
| + } |
| |
| for (i = 0; i < GPIO_MAX; i++) { |
| if (gpio_flags[i] != GPIOD_IN || !sfp->gpio[i]) |