@@ -446,6 +446,18 @@ struct dsa_switch_ops {
bool tx_pause, bool rx_pause);
void (*phylink_fixed_state)(struct dsa_switch *ds, int port,
struct phylink_link_state *state);
+ void (*phylink_pcs_get_state)(struct dsa_switch *ds, int port,
+ struct phylink_link_state *state);
+ int (*phylink_pcs_config)(struct dsa_switch *ds, int port,
+ unsigned int mode,
+ phy_interface_t interface,
+ const unsigned long *advertising);
+ void (*phylink_pcs_an_restart)(struct dsa_switch *ds, int port);
+ void (*phylink_pcs_link_up)(struct dsa_switch *ds, int port,
+ unsigned int mode,
+ phy_interface_t interface, int speed,
+ int duplex);
+
/*
* ethtool hardware statistics.
*/
@@ -169,6 +169,7 @@ int dsa_port_vid_del(struct dsa_port *dp, u16 vid);
int dsa_port_link_register_of(struct dsa_port *dp);
void dsa_port_link_unregister_of(struct dsa_port *dp);
extern const struct phylink_mac_ops dsa_port_phylink_mac_ops;
+extern const struct phylink_pcs_ops dsa_port_phylink_pcs_ops;
/* slave.c */
extern const struct dsa_device_ops notag_netdev_ops;
@@ -592,6 +592,52 @@ const struct phylink_mac_ops dsa_port_phylink_mac_ops = {
.mac_link_up = dsa_port_phylink_mac_link_up,
};
+static void dsa_port_pcs_get_state(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;
+
+ ds->ops->phylink_pcs_get_state(ds, dp->index, state);
+}
+
+static void dsa_port_pcs_an_restart(struct phylink_config *config)
+{
+ struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
+ struct dsa_switch *ds = dp->ds;
+
+ ds->ops->phylink_pcs_an_restart(ds, dp->index);
+}
+
+static int dsa_port_pcs_config(struct phylink_config *config,
+ unsigned int mode, phy_interface_t interface,
+ const unsigned long *advertising)
+{
+ struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
+ struct dsa_switch *ds = dp->ds;
+
+ return ds->ops->phylink_pcs_config(ds, dp->index, mode, interface,
+ advertising);
+}
+
+static void dsa_port_pcs_link_up(struct phylink_config *config,
+ unsigned int mode, phy_interface_t interface,
+ int speed, int duplex)
+{
+ struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
+ struct dsa_switch *ds = dp->ds;
+
+ ds->ops->phylink_pcs_link_up(ds, dp->index, mode, interface, speed,
+ duplex);
+}
+
+const struct phylink_pcs_ops dsa_port_phylink_pcs_ops = {
+ .pcs_get_state = dsa_port_pcs_get_state,
+ .pcs_config = dsa_port_pcs_config,
+ .pcs_an_restart = dsa_port_pcs_an_restart,
+ .pcs_link_up = dsa_port_pcs_link_up,
+};
+
static int dsa_port_setup_phy_of(struct dsa_port *dp, bool enable)
{
struct dsa_switch *ds = dp->ds;
@@ -1650,6 +1650,12 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev)
if (ds->ops->get_phy_flags)
phy_flags = ds->ops->get_phy_flags(ds, dp->index);
+ if (ds->ops->phylink_pcs_get_state &&
+ ds->ops->phylink_pcs_an_restart &&
+ ds->ops->phylink_pcs_config &&
+ ds->ops->phylink_pcs_link_up)
+ phylink_add_pcs(dp->pl, &dsa_port_phylink_pcs_ops);
+
ret = phylink_of_phy_connect(dp->pl, port_dn, phy_flags);
if (ret == -ENODEV && ds->slave_mii_bus) {
/* We could not connect to a designated PHY or SFP, so try to
In order to support split PCS using PHYLINK properly, we need to add a phylink_pcs_ops structure. Note that a DSA driver that wants to use these needs to implement all 4 of them: the DSA core checks the presence of these 4 function pointers in dsa_switch_ops and only then does it add a PCS to PHYLINK. This is done in order to preserve compatibility with drivers that have not yet been converted, or don't need, a split PCS setup. Also, when pcs_get_state() and pcs_an_restart() are present, their mac counterparts (mac_pcs_get_state(), mac_an_restart()) will no longer get called, as can be seen in phylink.c. Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com> --- Changes in v3: * patch added include/net/dsa.h | 12 ++++++++++++ net/dsa/dsa_priv.h | 1 + net/dsa/port.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ net/dsa/slave.c | 6 ++++++ 4 files changed, 65 insertions(+)