mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 03:10:12 +00:00
Merge branch 'mv88e6xxx-phylink-prepare'
Russell King says: ==================== net: dsa: mv88e6xxx: prepare for phylink_pcs conversion These two patches provide some preparation for converting the mv88e6xxx DSA driver to use phylink_pcs rather than bolting the serdes bits into the MAC calls. In order to correctly drive mv88e6xxx hardware when the PCS code is split, we need to force the link down while changing the configuration of a port. This is provided for via the mac_prepare() and mac_finish() methods, but DSA does not forward these on to DSA drivers. Patch 1 adds support to the DSA core to forward these two methods to DSA drivers, and patch 2 moves the code from mv88e6xxx_mac_config() into the respective methods. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
eba7dbc5eb
3 changed files with 83 additions and 20 deletions
|
@ -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,
|
||||
|
|
|
@ -867,9 +867,15 @@ struct dsa_switch_ops {
|
|||
phy_interface_t iface);
|
||||
int (*phylink_mac_link_state)(struct dsa_switch *ds, int port,
|
||||
struct phylink_link_state *state);
|
||||
int (*phylink_mac_prepare)(struct dsa_switch *ds, int port,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface);
|
||||
void (*phylink_mac_config)(struct dsa_switch *ds, int port,
|
||||
unsigned int mode,
|
||||
const struct phylink_link_state *state);
|
||||
int (*phylink_mac_finish)(struct dsa_switch *ds, int port,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface);
|
||||
void (*phylink_mac_an_restart)(struct dsa_switch *ds, int port);
|
||||
void (*phylink_mac_link_down)(struct dsa_switch *ds, int port,
|
||||
unsigned int mode,
|
||||
|
|
|
@ -1603,6 +1603,21 @@ dsa_port_phylink_mac_select_pcs(struct phylink_config *config,
|
|||
return pcs;
|
||||
}
|
||||
|
||||
static int dsa_port_phylink_mac_prepare(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
int err = 0;
|
||||
|
||||
if (ds->ops->phylink_mac_prepare)
|
||||
err = ds->ops->phylink_mac_prepare(ds, dp->index, mode,
|
||||
interface);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void dsa_port_phylink_mac_config(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
const struct phylink_link_state *state)
|
||||
|
@ -1616,6 +1631,21 @@ static void dsa_port_phylink_mac_config(struct phylink_config *config,
|
|||
ds->ops->phylink_mac_config(ds, dp->index, mode, state);
|
||||
}
|
||||
|
||||
static int dsa_port_phylink_mac_finish(struct phylink_config *config,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
int err = 0;
|
||||
|
||||
if (ds->ops->phylink_mac_finish)
|
||||
err = ds->ops->phylink_mac_finish(ds, dp->index, mode,
|
||||
interface);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void dsa_port_phylink_mac_an_restart(struct phylink_config *config)
|
||||
{
|
||||
struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
|
||||
|
@ -1671,7 +1701,9 @@ static const struct phylink_mac_ops dsa_port_phylink_mac_ops = {
|
|||
.validate = dsa_port_phylink_validate,
|
||||
.mac_select_pcs = dsa_port_phylink_mac_select_pcs,
|
||||
.mac_pcs_get_state = dsa_port_phylink_mac_pcs_get_state,
|
||||
.mac_prepare = dsa_port_phylink_mac_prepare,
|
||||
.mac_config = dsa_port_phylink_mac_config,
|
||||
.mac_finish = dsa_port_phylink_mac_finish,
|
||||
.mac_an_restart = dsa_port_phylink_mac_an_restart,
|
||||
.mac_link_down = dsa_port_phylink_mac_link_down,
|
||||
.mac_link_up = dsa_port_phylink_mac_link_up,
|
||||
|
|
Loading…
Reference in a new issue