lkml.org 
[lkml]   [2019]   [Feb]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 49/71] net: sfp: do not probe SFP module before were attached
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Russell King <rmk+kernel@armlinux.org.uk>

    [ Upstream commit b5bfc21af5cb3d53f9cee0ef82eaa43762a90f81 ]

    When we probe a SFP module, we expect to be able to call the upstream
    device's module_insert() function so that the upstream link can be
    configured. However, when the upstream device is delayed, we currently
    may end up probing the module before the upstream device is available,
    and lose the module_insert() call.

    Avoid this by holding off probing the module until the SFP bus is
    properly connected to both the SFP socket driver and the upstream
    driver.

    Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/net/phy/sfp-bus.c | 2 ++
    drivers/net/phy/sfp.c | 30 +++++++++++++++++++++---------
    drivers/net/phy/sfp.h | 2 ++
    3 files changed, 25 insertions(+), 9 deletions(-)

    --- a/drivers/net/phy/sfp-bus.c
    +++ b/drivers/net/phy/sfp-bus.c
    @@ -276,6 +276,7 @@ static int sfp_register_bus(struct sfp_b
    return ret;
    }
    }
    + bus->socket_ops->attach(bus->sfp);
    if (bus->started)
    bus->socket_ops->start(bus->sfp);
    bus->registered = true;
    @@ -289,6 +290,7 @@ static void sfp_unregister_bus(struct sf
    if (bus->registered) {
    if (bus->started)
    bus->socket_ops->stop(bus->sfp);
    + bus->socket_ops->detach(bus->sfp);
    if (bus->phydev && ops && ops->disconnect_phy)
    ops->disconnect_phy(bus->upstream);
    }
    --- a/drivers/net/phy/sfp.c
    +++ b/drivers/net/phy/sfp.c
    @@ -114,6 +114,7 @@ struct sfp {

    struct gpio_desc *gpio[GPIO_MAX];

    + bool attached;
    unsigned int state;
    struct delayed_work poll;
    struct delayed_work timeout;
    @@ -500,7 +501,7 @@ static void sfp_sm_event(struct sfp *sfp
    */
    switch (sfp->sm_mod_state) {
    default:
    - if (event == SFP_E_INSERT) {
    + if (event == SFP_E_INSERT && sfp->attached) {
    sfp_module_tx_disable(sfp);
    sfp_sm_ins_next(sfp, SFP_MOD_PROBE, T_PROBE_INIT);
    }
    @@ -628,6 +629,19 @@ static void sfp_sm_event(struct sfp *sfp
    mutex_unlock(&sfp->sm_mutex);
    }

    +static void sfp_attach(struct sfp *sfp)
    +{
    + sfp->attached = true;
    + if (sfp->state & SFP_F_PRESENT)
    + sfp_sm_event(sfp, SFP_E_INSERT);
    +}
    +
    +static void sfp_detach(struct sfp *sfp)
    +{
    + sfp->attached = false;
    + sfp_sm_event(sfp, SFP_E_REMOVE);
    +}
    +
    static void sfp_start(struct sfp *sfp)
    {
    sfp_sm_event(sfp, SFP_E_DEV_UP);
    @@ -687,6 +701,8 @@ static int sfp_module_eeprom(struct sfp
    }

    static const struct sfp_socket_ops sfp_module_ops = {
    + .attach = sfp_attach,
    + .detach = sfp_detach,
    .start = sfp_start,
    .stop = sfp_stop,
    .module_info = sfp_module_info,
    @@ -829,10 +845,6 @@ static int sfp_probe(struct platform_dev
    sfp->set_state = sfp_gpio_set_state;
    }

    - sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
    - if (!sfp->sfp_bus)
    - return -ENOMEM;
    -
    /* Get the initial state, and always signal TX disable,
    * since the network interface will not be up.
    */
    @@ -843,10 +855,6 @@ static int sfp_probe(struct platform_dev
    sfp->state |= SFP_F_RATE_SELECT;
    sfp_set_state(sfp, sfp->state);
    sfp_module_tx_disable(sfp);
    - rtnl_lock();
    - if (sfp->state & SFP_F_PRESENT)
    - 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])
    @@ -879,6 +887,10 @@ static int sfp_remove(struct platform_de

    sfp_unregister_socket(sfp->sfp_bus);

    + sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
    + if (!sfp->sfp_bus)
    + return -ENOMEM;
    +
    return 0;
    }

    --- a/drivers/net/phy/sfp.h
    +++ b/drivers/net/phy/sfp.h
    @@ -7,6 +7,8 @@
    struct sfp;

    struct sfp_socket_ops {
    + void (*attach)(struct sfp *sfp);
    + void (*detach)(struct sfp *sfp);
    void (*start)(struct sfp *sfp);
    void (*stop)(struct sfp *sfp);
    int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo);

    \
     
     \ /
      Last update: 2019-02-25 23:00    [W:4.291 / U:0.080 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site