diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 34ca12aec61b3c72886bdd9527362263401b73ab..0f23bec431c1c3be8c6181cc04bb5b3a857df37c 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -480,8 +480,8 @@ static void phylink_get_fixed_state(struct phylink *pl, struct phylink_link_state *state) { *state = pl->link_config; - if (pl->get_fixed_state) - pl->get_fixed_state(pl->netdev, state); + if (pl->config->get_fixed_state) + pl->config->get_fixed_state(pl->config, state); else if (pl->link_gpio) state->link = !!gpiod_get_value_cansleep(pl->link_gpio); @@ -1044,32 +1044,6 @@ void phylink_disconnect_phy(struct phylink *pl) } EXPORT_SYMBOL_GPL(phylink_disconnect_phy); -/** - * phylink_fixed_state_cb() - allow setting a fixed link callback - * @pl: a pointer to a &struct phylink returned from phylink_create() - * @cb: callback to execute to determine the fixed link state. - * - * The MAC driver should call this driver when the state of its link - * can be determined through e.g: an out of band MMIO register. - */ -int phylink_fixed_state_cb(struct phylink *pl, - void (*cb)(struct net_device *dev, - struct phylink_link_state *state)) -{ - /* It does not make sense to let the link be overriden unless we use - * MLO_AN_FIXED - */ - if (pl->cfg_link_an_mode != MLO_AN_FIXED) - return -EINVAL; - - mutex_lock(&pl->state_mutex); - pl->get_fixed_state = cb; - mutex_unlock(&pl->state_mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(phylink_fixed_state_cb); - /** * phylink_mac_change() - notify phylink of a change in MAC state * @pl: a pointer to a &struct phylink returned from phylink_create() @@ -1106,6 +1080,8 @@ static irqreturn_t phylink_link_handler(int irq, void *data) */ void phylink_start(struct phylink *pl) { + bool poll = false; + ASSERT_RTNL(); phylink_info(pl, "configuring for %s/%s link mode\n", @@ -1142,10 +1118,18 @@ void phylink_start(struct phylink *pl) irq = 0; } if (irq <= 0) - mod_timer(&pl->link_poll, jiffies + HZ); + poll = true; + } + + switch (pl->cfg_link_an_mode) { + case MLO_AN_FIXED: + poll |= pl->config->poll_fixed_state; + break; + case MLO_AN_INBAND: + poll |= pl->config->pcs_poll; + break; } - if ((pl->cfg_link_an_mode == MLO_AN_FIXED && pl->get_fixed_state) || - pl->config->pcs_poll) + if (poll) mod_timer(&pl->link_poll, jiffies + HZ); if (pl->phydev) phy_start(pl->phydev); diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 3f8d37ec55030b10512373f88bf2f76af44f502b..cc5b452a184e530847422761289f082fce50cdc6 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -67,6 +67,9 @@ struct phylink_config { struct device *dev; enum phylink_op_type type; bool pcs_poll; + bool poll_fixed_state; + void (*get_fixed_state)(struct phylink_config *config, + struct phylink_link_state *state); }; /** @@ -366,9 +369,6 @@ void phylink_destroy(struct phylink *); int phylink_connect_phy(struct phylink *, struct phy_device *); int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags); void phylink_disconnect_phy(struct phylink *); -int phylink_fixed_state_cb(struct phylink *, - void (*cb)(struct net_device *dev, - struct phylink_link_state *)); void phylink_mac_change(struct phylink *, bool up); diff --git a/net/dsa/slave.c b/net/dsa/slave.c index f2c241cf3a8037834ba9f31b4e4c08a6aff1973d..1035230771ae88795fc6bc06792e4ce757bd1ef5 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1590,10 +1590,10 @@ void dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up) } EXPORT_SYMBOL_GPL(dsa_port_phylink_mac_change); -static void dsa_slave_phylink_fixed_state(struct net_device *dev, +static void dsa_slave_phylink_fixed_state(struct phylink_config *config, struct phylink_link_state *state) { - struct dsa_port *dp = dsa_slave_to_port(dev); + struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); struct dsa_switch *ds = dp->ds; /* No need to check that this operation is valid, the callback would @@ -1633,6 +1633,15 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev) dp->pl_config.dev = &slave_dev->dev; dp->pl_config.type = PHYLINK_NETDEV; + /* The get_fixed_state callback takes precedence over polling the + * link GPIO in PHYLINK (see phylink_get_fixed_state). Only set + * this if the switch provides such a callback. + */ + if (ds->ops->phylink_fixed_state) { + dp->pl_config.get_fixed_state = dsa_slave_phylink_fixed_state; + dp->pl_config.poll_fixed_state = true; + } + dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), mode, &dsa_port_phylink_mac_ops); if (IS_ERR(dp->pl)) { @@ -1641,13 +1650,6 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev) return PTR_ERR(dp->pl); } - /* Register only if the switch provides such a callback, since this - * callback takes precedence over polling the link GPIO in PHYLINK - * (see phylink_get_fixed_state). - */ - if (ds->ops->phylink_fixed_state) - phylink_fixed_state_cb(dp->pl, dsa_slave_phylink_fixed_state); - if (ds->ops->get_phy_flags) phy_flags = ds->ops->get_phy_flags(ds, dp->index);