From: Florian Fainelli <florian.fainelli@broadcom.com>
To: netdev@vger.kernel.org
Cc: Florian Fainelli <florian.fainelli@broadcom.com>,
Jonas Gorski <jonas.gorski@gmail.com>,
Andrew Lunn <andrew@lunn.ch>, Vladimir Oltean <olteanv@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@kernel.org>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Russell King <linux@armlinux.org.uk>,
"Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>,
linux-kernel@vger.kernel.org (open list)
Subject: [PATCH net 2/6 RESEND] net: dsa: b53: manage SerDes power through the PCS callbacks
Date: Thu, 22 Oct 2026 15:56:52 -0700 [thread overview]
Message-ID: <20261022225656.1387306-3-florian.fainelli@broadcom.com> (raw)
In-Reply-To: <20261022225656.1387306-1-florian.fainelli@broadcom.com>
Powering down the SerDes from mac_link_down() prevents the PCS from
observing link recovery. This also ties PCS power management to in-band
802.3z mode, leaving SGMII and other negotiation modes inconsistent.
Implement pcs_enable() and pcs_disable() so that phylink controls the
lane lifetime independently of individual link transitions. Remove the
MAC-to-SerDes power callback and perform read-modify-write operations
under the register mutex.
Fixes: 0e01491de646 ("net: dsa: b53: Add SerDes support")
Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
---
drivers/net/dsa/b53/b53_common.c | 8 ----
drivers/net/dsa/b53/b53_priv.h | 3 --
drivers/net/dsa/b53/b53_serdes.c | 70 +++++++++++++++++++++++---------
drivers/net/dsa/b53/b53_serdes.h | 2 -
drivers/net/dsa/b53/b53_srab.c | 1 -
5 files changed, 51 insertions(+), 33 deletions(-)
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 3f8f956aab82..09de3520e71a 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1630,10 +1630,6 @@ static void b53_phylink_mac_link_down(struct phylink_config *config,
b53_force_link(dev, port, false);
return;
}
-
- if (phy_interface_mode_is_8023z(interface) &&
- dev->ops->serdes_link_set)
- dev->ops->serdes_link_set(dev, port, mode, interface, false);
}
static void b53_phylink_mac_link_up(struct phylink_config *config,
@@ -1672,10 +1668,6 @@ static void b53_phylink_mac_link_up(struct phylink_config *config,
b53_force_link(dev, port, true);
return;
}
-
- if (phy_interface_mode_is_8023z(interface) &&
- dev->ops->serdes_link_set)
- dev->ops->serdes_link_set(dev, port, mode, interface, true);
}
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index 29cca7945df7..cebbebe4ae0f 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -54,9 +54,6 @@ struct b53_io_ops {
int port,
phy_interface_t interface);
u8 (*serdes_map_lane)(struct b53_device *dev, int port);
- void (*serdes_link_set)(struct b53_device *dev, int port,
- unsigned int mode, phy_interface_t interface,
- bool link_up);
};
struct b53_arl_entry;
diff --git a/drivers/net/dsa/b53/b53_serdes.c b/drivers/net/dsa/b53/b53_serdes.c
index c90894877626..87771e3788f7 100644
--- a/drivers/net/dsa/b53/b53_serdes.c
+++ b/drivers/net/dsa/b53/b53_serdes.c
@@ -107,6 +107,39 @@ static int b53_serdes_read(struct b53_device *dev, u8 lane,
return ret;
}
+/* Return one if the register changed, zero if unchanged, or an error. */
+static int b53_serdes_modify(struct b53_device *dev, u8 lane, u8 offset,
+ u16 block, u16 mask, u16 set)
+{
+ int ret, old;
+ u16 new;
+
+ mutex_lock(&dev->reg_mutex);
+ ret = b53_serdes_set_lane(dev, lane);
+ if (ret)
+ goto out;
+
+ old = b53_serdes_read_blk(dev, offset, block);
+ if (old < 0) {
+ ret = old;
+ goto out;
+ }
+
+ new = (old & ~mask) | set;
+ if (new == old)
+ goto out;
+
+ ret = b53_serdes_write_blk(dev, offset, block, new);
+ if (!ret)
+ ret = 1;
+out:
+ if (ret < 0)
+ dev->serdes_lane = B53_INVALID_LANE;
+ mutex_unlock(&dev->reg_mutex);
+
+ return ret;
+}
+
static void b53_serdes_error(struct b53_device *dev, u8 lane, int ret)
{
if (ret < 0)
@@ -202,32 +235,31 @@ static void b53_serdes_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
state->pause |= MLO_PAUSE_TX;
}
-void b53_serdes_link_set(struct b53_device *dev, int port, unsigned int mode,
- phy_interface_t interface, bool link_up)
+static int b53_serdes_enable(struct phylink_pcs *pcs)
{
- u8 lane = b53_serdes_map_lane(dev, port);
- int reg;
+ struct b53_pcs *priv = pcs_to_b53_pcs(pcs);
+ int ret;
- if (lane == B53_INVALID_LANE)
- return;
+ ret = b53_serdes_modify(priv->dev, priv->lane,
+ B53_SERDES_MII_REG(MII_BMCR), SERDES_MII_BLK,
+ BMCR_PDOWN, 0);
+ return ret < 0 ? ret : 0;
+}
- reg = b53_serdes_read(dev, lane, B53_SERDES_MII_REG(MII_BMCR),
- SERDES_MII_BLK);
- if (reg < 0)
- goto out;
+static void b53_serdes_disable(struct phylink_pcs *pcs)
+{
+ struct b53_pcs *priv = pcs_to_b53_pcs(pcs);
+ int ret;
- if (link_up)
- reg &= ~BMCR_PDOWN;
- else
- reg |= BMCR_PDOWN;
- reg = b53_serdes_write(dev, lane, B53_SERDES_MII_REG(MII_BMCR),
- SERDES_MII_BLK, reg);
-out:
- b53_serdes_error(dev, lane, reg);
+ ret = b53_serdes_modify(priv->dev, priv->lane,
+ B53_SERDES_MII_REG(MII_BMCR), SERDES_MII_BLK,
+ BMCR_PDOWN, BMCR_PDOWN);
+ b53_serdes_error(priv->dev, priv->lane, ret);
}
-EXPORT_SYMBOL(b53_serdes_link_set);
static const struct phylink_pcs_ops b53_pcs_ops = {
+ .pcs_enable = b53_serdes_enable,
+ .pcs_disable = b53_serdes_disable,
.pcs_get_state = b53_serdes_get_state,
.pcs_config = b53_serdes_config,
.pcs_an_restart = b53_serdes_an_restart,
diff --git a/drivers/net/dsa/b53/b53_serdes.h b/drivers/net/dsa/b53/b53_serdes.h
index 3d367c4df4d9..6c851838457e 100644
--- a/drivers/net/dsa/b53/b53_serdes.h
+++ b/drivers/net/dsa/b53/b53_serdes.h
@@ -107,8 +107,6 @@ static inline u8 b53_serdes_map_lane(struct b53_device *dev, int port)
return dev->ops->serdes_map_lane(dev, port);
}
-void b53_serdes_link_set(struct b53_device *dev, int port, unsigned int mode,
- phy_interface_t interface, bool link_up);
struct phylink_pcs *b53_serdes_phylink_mac_select_pcs(struct b53_device *dev,
int port,
phy_interface_t interface);
diff --git a/drivers/net/dsa/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c
index 83a03fca142a..9988a83fa7b7 100644
--- a/drivers/net/dsa/b53/b53_srab.c
+++ b/drivers/net/dsa/b53/b53_srab.c
@@ -493,7 +493,6 @@ static const struct b53_io_ops b53_srab_ops = {
#if IS_ENABLED(CONFIG_B53_SERDES)
.phylink_mac_select_pcs = b53_serdes_phylink_mac_select_pcs,
.serdes_map_lane = b53_srab_serdes_map_lane,
- .serdes_link_set = b53_serdes_link_set,
#endif
};
--
2.53.0
next prev parent reply other threads:[~2026-10-22 22:57 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-22 22:56 [PATCH net 0/6 RESEND] net: dsa: b53: PCS fixes Florian Fainelli
2026-10-22 22:56 ` [PATCH net 1/6 RESEND] net: dsa: b53: serialize SerDes register transactions Florian Fainelli
2026-10-22 22:56 ` Florian Fainelli [this message]
2026-10-26 23:47 ` [PATCH net 2/6 RESEND] net: dsa: b53: manage SerDes power through the PCS callbacks netdev-bot+sashiko
2026-10-27 17:31 ` Florian Fainelli
2026-10-22 22:56 ` [PATCH net 3/6 RESEND] net: dsa: b53: constrain SerDes interfaces to initialized PCSes Florian Fainelli
2026-10-26 23:47 ` netdev-bot+sashiko
2026-10-27 18:05 ` Florian Fainelli
2026-10-22 22:56 ` [PATCH net 4/6 RESEND] net: dsa: b53: configure PCS negotiation and forced link parameters Florian Fainelli
2026-10-26 23:47 ` netdev-bot+sashiko
2026-10-27 18:06 ` Florian Fainelli
2026-10-22 22:56 ` [PATCH net 5/6 RESEND] net: dsa: b53: report link state through the PCS Florian Fainelli
2026-10-26 23:47 ` netdev-bot+sashiko
2026-10-27 18:07 ` Florian Fainelli
2026-10-22 22:56 ` [PATCH net 6/6 RESEND] net: dsa: b53: apply resolved link settings to serial port MACs Florian Fainelli
2026-10-26 23:47 ` netdev-bot+sashiko
2026-10-27 18:08 ` Florian Fainelli
2026-10-27 9:31 ` [PATCH net 0/6 RESEND] net: dsa: b53: PCS fixes Chenguang Zhao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261022225656.1387306-3-florian.fainelli@broadcom.com \
--to=florian.fainelli@broadcom.com \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=jonas.gorski@gmail.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=pabeni@redhat.com \
--cc=rmk+kernel@armlinux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.