summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c48
-rw-r--r--drivers/net/phy/phylink.c15
-rw-r--r--include/linux/phylink.h2
-rw-r--r--include/net/dsa.h2
-rw-r--r--net/dsa/port.c17
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,