diff options
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 48 | ||||
-rw-r--r-- | drivers/net/phy/phylink.c | 15 | ||||
-rw-r--r-- | include/linux/phylink.h | 2 | ||||
-rw-r--r-- | include/net/dsa.h | 2 | ||||
-rw-r--r-- | net/dsa/port.c | 17 |
5 files changed, 56 insertions, 28 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 9e1a291eda7d..d728fdf6f826 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -430,37 +430,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) @@ -492,6 +476,19 @@ static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port) return !!(reg & MV88E6XXX_PORT_STS_PHY_DETECT); } +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 const u8 mv88e6185_phy_interface_modes[] = { [MV88E6185_PORT_STS_CMODE_GMII_FD] = PHY_INTERFACE_MODE_GMII, [MV88E6185_PORT_STS_CMODE_MII_100_FD_PS] = PHY_INTERFACE_MODE_MII, @@ -2847,16 +2844,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; @@ -6156,6 +6147,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .teardown = mv88e6xxx_teardown, .port_setup = mv88e6xxx_port_setup, .port_teardown = mv88e6xxx_port_teardown, + .phylink_default_config = mv88e6xxx_default_config, .phylink_get_caps = mv88e6xxx_get_caps, .phylink_mac_select_pcs = mv88e6xxx_mac_select_pcs, .phylink_mac_prepare = mv88e6xxx_mac_prepare, diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index dccf72d78ea0..4292bc650f2b 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1725,6 +1725,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)); diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 29b50a2c96e0..03f855eabd37 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -171,6 +171,8 @@ struct phylink_config { * The individual methods are described more fully below. */ struct phylink_mac_ops { + void (*default_config)(struct phylink_config *config, + struct phylink_link_state *state); void (*validate)(struct phylink_config *config, unsigned long *supported, struct phylink_link_state *state); diff --git a/include/net/dsa.h b/include/net/dsa.h index 5ad8924935ef..9abbbfba09a1 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -740,6 +740,8 @@ struct dsa_switch_ops { /* * PHYLINK integration */ + void (*phylink_default_config)(struct dsa_switch *ds, int port, + struct phylink_link_state *state); void (*phylink_get_caps)(struct dsa_switch *ds, int port, struct phylink_config *config); void (*phylink_validate)(struct dsa_switch *ds, int port, diff --git a/net/dsa/port.c b/net/dsa/port.c index db8ca6c54979..bc58cb7d2042 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -989,6 +989,22 @@ static struct phy_device *dsa_port_get_phy_device(struct dsa_port *dp) return phydev; } +static void dsa_port_phylink_default_config(struct phylink_config *config, + struct phylink_link_state *state) +{ + struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); + struct dsa_switch *ds = dp->ds; + + if (dp->type == DSA_PORT_TYPE_USER || + !ds->ops->phylink_default_config) { + dev_err(ds->dev, "p%d: improper configuration for port\n", + dp->index); + return; + } + + ds->ops->phylink_default_config(ds, dp->index, state); +} + static void dsa_port_phylink_validate(struct phylink_config *config, unsigned long *supported, struct phylink_link_state *state) @@ -1109,6 +1125,7 @@ static void dsa_port_phylink_mac_link_up(struct phylink_config *config, } static const struct phylink_mac_ops dsa_port_phylink_mac_ops = { + .default_config = dsa_port_phylink_default_config, .validate = dsa_port_phylink_validate, .mac_select_pcs = dsa_port_phylink_mac_select_pcs, .mac_prepare = dsa_port_phylink_mac_prepare, |