summaryrefslogtreecommitdiff
path: root/drivers/net/phy
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2020-07-21 12:04:46 +0100
committerDavid S. Miller <davem@davemloft.net>2020-07-21 15:46:51 -0700
commit7137e18f6f889a67046d5004e1690a32d7d2108d (patch)
tree714c34515e11dd4fd8637811a65e88cf2d7a2734 /drivers/net/phy
parentb7ad14c2fe2d4b2abee491e3adfa3d0123aa2d8c (diff)
net: phylink: add struct phylink_pcs
Add a way for MAC PCS to have private data while keeping independence from struct phylink_config, which is used for the MAC itself. We need this independence as we will have stand-alone code for PCS that is independent of the MAC. Introduce struct phylink_pcs, which is designed to be embedded in a driver private data structure. This structure does not include a mdio_device as there are PCS implementations such as the Marvell DSA and network drivers where this is not necessary. Reviewed-by: Ioana Ciornei <ioana.ciornei@nxp.com> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy')
-rw-r--r--drivers/net/phy/phylink.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index d554a0fbb4f3..b57cd2142786 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -43,6 +43,7 @@ struct phylink {
const struct phylink_mac_ops *mac_ops;
const struct phylink_pcs_ops *pcs_ops;
struct phylink_config *config;
+ struct phylink_pcs *pcs;
struct device *dev;
unsigned int old_link_state:1;
@@ -427,7 +428,7 @@ static void phylink_mac_pcs_an_restart(struct phylink *pl)
phy_interface_mode_is_8023z(pl->link_config.interface) &&
phylink_autoneg_inband(pl->cur_link_an_mode)) {
if (pl->pcs_ops)
- pl->pcs_ops->pcs_an_restart(pl->config);
+ pl->pcs_ops->pcs_an_restart(pl->pcs);
else
pl->mac_ops->mac_an_restart(pl->config);
}
@@ -453,7 +454,7 @@ static void phylink_major_config(struct phylink *pl, bool restart,
phylink_mac_config(pl, state);
if (pl->pcs_ops) {
- err = pl->pcs_ops->pcs_config(pl->config, pl->cur_link_an_mode,
+ err = pl->pcs_ops->pcs_config(pl->pcs, pl->cur_link_an_mode,
state->interface,
state->advertising,
!!(pl->link_config.pause &
@@ -506,7 +507,7 @@ static int phylink_change_inband_advert(struct phylink *pl)
* restart negotiation if the pcs_config() helper indicates that
* the programmed advertisement has changed.
*/
- ret = pl->pcs_ops->pcs_config(pl->config, pl->cur_link_an_mode,
+ ret = pl->pcs_ops->pcs_config(pl->pcs, pl->cur_link_an_mode,
pl->link_config.interface,
pl->link_config.advertising,
!!(pl->link_config.pause & MLO_PAUSE_AN));
@@ -533,7 +534,7 @@ static void phylink_mac_pcs_get_state(struct phylink *pl,
state->link = 1;
if (pl->pcs_ops)
- pl->pcs_ops->pcs_get_state(pl->config, state);
+ pl->pcs_ops->pcs_get_state(pl->pcs, state);
else
pl->mac_ops->mac_pcs_get_state(pl->config, state);
}
@@ -604,7 +605,7 @@ static void phylink_link_up(struct phylink *pl,
pl->cur_interface = link_state.interface;
if (pl->pcs_ops && pl->pcs_ops->pcs_link_up)
- pl->pcs_ops->pcs_link_up(pl->config, pl->cur_link_an_mode,
+ pl->pcs_ops->pcs_link_up(pl->pcs, pl->cur_link_an_mode,
pl->cur_interface,
link_state.speed, link_state.duplex);
@@ -863,11 +864,26 @@ struct phylink *phylink_create(struct phylink_config *config,
}
EXPORT_SYMBOL_GPL(phylink_create);
-void phylink_add_pcs(struct phylink *pl, const struct phylink_pcs_ops *ops)
+/**
+ * phylink_set_pcs() - set the current PCS for phylink to use
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ * @pcs: a pointer to the &struct phylink_pcs
+ *
+ * Bind the MAC PCS to phylink. This may be called after phylink_create(),
+ * in mac_prepare() or mac_config() methods if it is desired to dynamically
+ * change the PCS.
+ *
+ * Please note that there are behavioural changes with the mac_config()
+ * callback if a PCS is present (denoting a newer setup) so removing a PCS
+ * is not supported, and if a PCS is going to be used, it must be registered
+ * by calling phylink_set_pcs() at the latest in the first mac_config() call.
+ */
+void phylink_set_pcs(struct phylink *pl, struct phylink_pcs *pcs)
{
- pl->pcs_ops = ops;
+ pl->pcs = pcs;
+ pl->pcs_ops = pcs->ops;
}
-EXPORT_SYMBOL_GPL(phylink_add_pcs);
+EXPORT_SYMBOL_GPL(phylink_set_pcs);
/**
* phylink_destroy() - cleanup and destroy the phylink instance
@@ -1212,6 +1228,8 @@ void phylink_start(struct phylink *pl)
break;
case MLO_AN_INBAND:
poll |= pl->config->pcs_poll;
+ if (pl->pcs)
+ poll |= pl->pcs->poll;
break;
}
if (poll)