From 6f85be7ce3fa31f378cda12c46b787dbfd1b6bc7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 17 Feb 2020 16:23:31 +0000 Subject: net: phylink/dsa: fix DSA and CPU links Signed-off-by: Russell King --- drivers/net/dsa/mv88e6xxx/chip.c | 48 +++++++++++++++++----------------------- drivers/net/phy/phylink.c | 15 +++++++++++++ 2 files changed, 35 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index f392613f6373..543bd9cdd3ca 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -428,37 +428,21 @@ static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, if (!chip->info->ops->port_set_link) return 0; - if (speed = SPEED_MAX) { - if (chip->info->ops->port_max_speed_mode) - mode = chip->info->ops->port_max_speed_mode(port); - if (chip->info->ops->port_max_speed) - speed = chip->info->ops->port_max_speed(port); - } - /* Port's MAC control must not be changed unless the link is down */ err = chip->info->ops->port_set_link(chip, port, LINK_FORCED_DOWN); if (err) return err; - if (chip->info->ops->port_set_speed_duplex) { - err = chip->info->ops->port_set_speed_duplex(chip, port, - speed, duplex); - if (err && err != -EOPNOTSUPP) - goto restore_link; - } - if (chip->info->ops->port_set_pause) { err = chip->info->ops->port_set_pause(chip, port, pause); if (err) - goto restore_link; + return err; } - err = mv88e6xxx_port_config_interface(chip, port, mode); -restore_link: if (chip->info->ops->port_set_link(chip, port, link)) dev_err(chip->dev, "p%d: failed to restore MAC's link\n", port); - return err; + return 0; } static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port) @@ -559,6 +543,19 @@ static int mv88e6xxx_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port, return 0; } +static void mv88e6xxx_default_config(struct dsa_switch *ds, int port, + struct phylink_link_state *state) +{ + struct mv88e6xxx_chip *chip = ds->priv; + + if (chip->info->ops->port_max_speed_mode) + state->interface = chip->info->ops->port_max_speed_mode(port); + + state->duplex = DUPLEX_FULL; + state->speed = chip->info->ops->port_max_speed(port); + state->link = true; +} + static void mv88e6065_phylink_validate(struct mv88e6xxx_chip *chip, int port, unsigned long *mask, struct phylink_link_state *state) @@ -2571,16 +2568,10 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) * state to any particular values on physical ports, but force the CPU * port and all DSA ports to their maximum bandwidth and full duplex. */ - if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) - err = mv88e6xxx_port_setup_mac(chip, port, LINK_FORCED_UP, - SPEED_MAX, DUPLEX_FULL, - PAUSE_OFF, - PHY_INTERFACE_MODE_NA); - else - err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED, - SPEED_UNFORCED, DUPLEX_UNFORCED, - PAUSE_ON, - PHY_INTERFACE_MODE_NA); + err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED, + SPEED_UNFORCED, DUPLEX_UNFORCED, + PAUSE_ON, + PHY_INTERFACE_MODE_NA); if (err) return err; @@ -5597,6 +5588,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .get_tag_protocol = mv88e6xxx_get_tag_protocol, .setup = mv88e6xxx_setup, .teardown = mv88e6xxx_teardown, + .phylink_default_config = mv88e6xxx_default_config, .phylink_validate = mv88e6xxx_validate, .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state, .phylink_mac_config = mv88e6xxx_mac_config, diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 6680de39e338..a32eb56d48f3 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1188,6 +1188,21 @@ void phylink_start(struct phylink *pl) ASSERT_RTNL(); + /* + * If no PHY or SFP attached, and but we're in PHY mode, + * attempt to pick up a default configuration. + */ + if (pl->cfg_link_an_mode == MLO_AN_PHY && !pl->phydev && !pl->sfp_bus) { + if (pl->mac_ops->default_config) { + pl->mac_ops->default_config(pl->config, + &pl->link_config); + pl->cfg_link_an_mode = MLO_AN_FIXED; + pl->cur_link_an_mode = MLO_AN_FIXED; + } else { + phylink_warn(pl, "no default configuration\n"); + } + } + phylink_info(pl, "configuring for %s/%s link mode\n", phylink_an_mode_str(pl->cur_link_an_mode), phy_modes(pl->link_config.interface)); -- cgit