From e17b4adfa24683a779851d5054b21fcc73fd5ed5 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Wed, 16 Aug 2023 14:02:11 +0100 Subject: net: dsa: add support for phylink managed EEE Add support to allow DSA drivers to use phylink managed EEE, with only needing support for controlling the LPI state. Signed-off-by: Russell King (Oracle) --- include/net/dsa.h | 3 +++ net/dsa/port.c | 22 ++++++++++++++++++++++ net/dsa/user.c | 42 ++++++++++++++++++++++++++---------------- 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index 82135fbdb1e6..55d3a879e44d 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -891,6 +891,9 @@ struct dsa_switch_ops { struct phy_device *phydev, int speed, int duplex, bool tx_pause, bool rx_pause); + void (*phylink_mac_disable_tx_lpi)(struct dsa_switch *ds, int port); + void (*phylink_mac_enable_tx_lpi)(struct dsa_switch *ds, int port, + u32 timer); void (*phylink_fixed_state)(struct dsa_switch *ds, int port, struct phylink_link_state *state); /* diff --git a/net/dsa/port.c b/net/dsa/port.c index c42dac87671b..8c52d5a87c17 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -1651,6 +1651,26 @@ static void dsa_port_phylink_mac_link_up(struct phylink_config *config, speed, duplex, tx_pause, rx_pause); } +static void dsa_port_phylink_mac_disable_tx_lpi(struct phylink_config *config) +{ + struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); + struct dsa_switch *ds = dp->ds; + + if (ds->ops->phylink_mac_disable_tx_lpi) + ds->ops->phylink_mac_disable_tx_lpi(ds, dp->index); + +} + +static void dsa_port_phylink_mac_enable_tx_lpi(struct phylink_config *config, + u32 timer) +{ + struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); + struct dsa_switch *ds = dp->ds; + + if (ds->ops->phylink_mac_enable_tx_lpi) + ds->ops->phylink_mac_enable_tx_lpi(ds, dp->index, timer); +} + static const struct phylink_mac_ops dsa_port_phylink_mac_ops = { .mac_select_pcs = dsa_port_phylink_mac_select_pcs, .mac_prepare = dsa_port_phylink_mac_prepare, @@ -1658,6 +1678,8 @@ static const struct phylink_mac_ops dsa_port_phylink_mac_ops = { .mac_finish = dsa_port_phylink_mac_finish, .mac_link_down = dsa_port_phylink_mac_link_down, .mac_link_up = dsa_port_phylink_mac_link_up, + .mac_disable_tx_lpi = dsa_port_phylink_mac_disable_tx_lpi, + .mac_enable_tx_lpi = dsa_port_phylink_mac_enable_tx_lpi, }; int dsa_port_phylink_create(struct dsa_port *dp) diff --git a/net/dsa/user.c b/net/dsa/user.c index d438884a4eb0..0c0f27418c2a 100644 --- a/net/dsa/user.c +++ b/net/dsa/user.c @@ -1251,16 +1251,21 @@ static int dsa_user_set_eee(struct net_device *dev, struct ethtool_eee *e) struct dsa_switch *ds = dp->ds; int ret; - /* Port's PHY and MAC both need to be EEE capable */ - if (!dev->phydev || !dp->pl) - return -ENODEV; + /* If the port is using phylink managed EEE, then get_mac_eee is + * unnecessary. + */ + if (!dp->pl_config.lpi_capabilities) { + /* Port's PHY and MAC both need to be EEE capable */ + if (!dev->phydev || !dp->pl) + return -ENODEV; - if (!ds->ops->set_mac_eee) - return -EOPNOTSUPP; + if (!ds->ops->set_mac_eee) + return -EOPNOTSUPP; - ret = ds->ops->set_mac_eee(ds, dp->index, e); - if (ret) - return ret; + ret = ds->ops->set_mac_eee(ds, dp->index, e); + if (ret) + return ret; + } return phylink_ethtool_set_eee(dp->pl, e); } @@ -1271,16 +1276,21 @@ static int dsa_user_get_eee(struct net_device *dev, struct ethtool_eee *e) struct dsa_switch *ds = dp->ds; int ret; - /* Port's PHY and MAC both need to be EEE capable */ - if (!dev->phydev || !dp->pl) - return -ENODEV; + /* If the port is using phylink managed EEE, then get_mac_eee is + * unnecessary. + */ + if (!dp->pl_config.lpi_capabilities) { + /* Port's PHY and MAC both need to be EEE capable */ + if (!dev->phydev || !dp->pl) + return -ENODEV; - if (!ds->ops->get_mac_eee) - return -EOPNOTSUPP; + if (!ds->ops->get_mac_eee) + return -EOPNOTSUPP; - ret = ds->ops->get_mac_eee(ds, dp->index, e); - if (ret) - return ret; + ret = ds->ops->get_mac_eee(ds, dp->index, e); + if (ret) + return ret; + } return phylink_ethtool_get_eee(dp->pl, e); } -- cgit