Commit 267d7692 authored by Russell King (Oracle)'s avatar Russell King (Oracle) Committed by David S. Miller
Browse files

net: dsa: mv88e6xxx: move link forcing to mac_prepare/mac_finish



Move the link forcing out of mac_config() and into the mac_prepare()
and mac_finish() methods. This results in no change to the order in
which these operations are performed, but does mean when we convert
mv88e6xxx to phylink_pcs support, we will continue to preserve this
ordering.

Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dd805cf3
Loading
Loading
Loading
Loading
+45 −20
Original line number Diff line number Diff line
@@ -841,29 +841,38 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port,
	}
}

static int mv88e6xxx_mac_prepare(struct dsa_switch *ds, int port,
				 unsigned int mode, phy_interface_t interface)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	int err = 0;

	/* In inband mode, the link may come up at any time while the link
	 * is not forced down. Force the link down while we reconfigure the
	 * interface mode.
	 */
	if (mode == MLO_AN_INBAND &&
	    chip->ports[port].interface != interface &&
	    chip->info->ops->port_set_link) {
		mv88e6xxx_reg_lock(chip);
		err = chip->info->ops->port_set_link(chip, port,
						     LINK_FORCED_DOWN);
		mv88e6xxx_reg_unlock(chip);
	}

	return err;
}

static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
				 unsigned int mode,
				 const struct phylink_link_state *state)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	struct mv88e6xxx_port *p;
	int err = 0;

	p = &chip->ports[port];

	mv88e6xxx_reg_lock(chip);

	if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) {
		/* In inband mode, the link may come up at any time while the
		 * link is not forced down. Force the link down while we
		 * reconfigure the interface mode.
		 */
		if (mode == MLO_AN_INBAND &&
		    p->interface != state->interface &&
		    chip->info->ops->port_set_link)
			chip->info->ops->port_set_link(chip, port,
						       LINK_FORCED_DOWN);

		err = mv88e6xxx_port_config_interface(chip, port,
						      state->interface);
		if (err && err != -EOPNOTSUPP)
@@ -880,24 +889,38 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
			err = 0;
	}

err_unlock:
	mv88e6xxx_reg_unlock(chip);

	if (err && err != -EOPNOTSUPP)
		dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port);
}

static int mv88e6xxx_mac_finish(struct dsa_switch *ds, int port,
				unsigned int mode, phy_interface_t interface)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	int err = 0;

	/* Undo the forced down state above after completing configuration
	 * irrespective of its state on entry, which allows the link to come
	 * up in the in-band case where there is no separate SERDES. Also
	 * ensure that the link can come up if the PPU is in use and we are
	 * in PHY mode (we treat the PPU as an effective in-band mechanism.)
	 */
	mv88e6xxx_reg_lock(chip);

	if (chip->info->ops->port_set_link &&
	    ((mode == MLO_AN_INBAND && p->interface != state->interface) ||
	    ((mode == MLO_AN_INBAND &&
	      chip->ports[port].interface != interface) ||
	     (mode == MLO_AN_PHY && mv88e6xxx_port_ppu_updates(chip, port))))
		chip->info->ops->port_set_link(chip, port, LINK_UNFORCED);
		err = chip->info->ops->port_set_link(chip, port, LINK_UNFORCED);

	p->interface = state->interface;

err_unlock:
	mv88e6xxx_reg_unlock(chip);

	if (err && err != -EOPNOTSUPP)
		dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port);
	chip->ports[port].interface = interface;

	return err;
}

static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,
@@ -7002,7 +7025,9 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
	.port_teardown		= mv88e6xxx_port_teardown,
	.phylink_get_caps	= mv88e6xxx_get_caps,
	.phylink_mac_link_state	= mv88e6xxx_serdes_pcs_get_state,
	.phylink_mac_prepare	= mv88e6xxx_mac_prepare,
	.phylink_mac_config	= mv88e6xxx_mac_config,
	.phylink_mac_finish	= mv88e6xxx_mac_finish,
	.phylink_mac_an_restart	= mv88e6xxx_serdes_pcs_an_restart,
	.phylink_mac_link_down	= mv88e6xxx_mac_link_down,
	.phylink_mac_link_up	= mv88e6xxx_mac_link_up,