* [PATCH v3 1/3] net: mscc: ocelot: extract ocelot_xmit_timestamp() helper
2026-02-08 22:55 [PATCH v3 0/3] net: mscc: ocelot: fix missing lock in ocelot_port_xmit() Ziyi Guo
@ 2026-02-08 22:56 ` Ziyi Guo
2026-02-08 22:56 ` [PATCH v3 2/3] net: mscc: ocelot: split xmit into FDMA and register injection paths Ziyi Guo
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Ziyi Guo @ 2026-02-08 22:56 UTC (permalink / raw)
To: Vladimir Oltean, Claudiu Manoil, Alexandre Belloni
Cc: UNGLinuxDriver, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev, linux-kernel, Ziyi Guo
Extract the PTP timestamp handling logic from ocelot_port_xmit() into a
separate ocelot_xmit_timestamp() helper function. This is a pure
refactor with no behavioral change.
The helper returns false if the skb was consumed (freed) due to a
timestamp request failure, and true if the caller should continue with
frame injection. The rew_op value is returned via pointer.
This prepares for splitting ocelot_port_xmit() into separate FDMA and
register injection paths in a subsequent patch.
Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>
---
drivers/net/ethernet/mscc/ocelot_net.c | 36 ++++++++++++++++----------
1 file changed, 22 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index 469784d3a1a6..ef4a6c768de9 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -551,33 +551,41 @@ static int ocelot_port_stop(struct net_device *dev)
return 0;
}
-static netdev_tx_t ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
+static bool ocelot_xmit_timestamp(struct ocelot *ocelot, int port,
+ struct sk_buff *skb, u32 *rew_op)
{
- struct ocelot_port_private *priv = netdev_priv(dev);
- struct ocelot_port *ocelot_port = &priv->port;
- struct ocelot *ocelot = ocelot_port->ocelot;
- int port = priv->port.index;
- u32 rew_op = 0;
-
- if (!static_branch_unlikely(&ocelot_fdma_enabled) &&
- !ocelot_can_inject(ocelot, 0))
- return NETDEV_TX_BUSY;
-
- /* Check if timestamping is needed */
if (ocelot->ptp && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
struct sk_buff *clone = NULL;
if (ocelot_port_txtstamp_request(ocelot, port, skb, &clone)) {
kfree_skb(skb);
- return NETDEV_TX_OK;
+ return false;
}
if (clone)
OCELOT_SKB_CB(skb)->clone = clone;
- rew_op = ocelot_ptp_rew_op(skb);
+ *rew_op = ocelot_ptp_rew_op(skb);
}
+ return true;
+}
+
+static netdev_tx_t ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct ocelot_port_private *priv = netdev_priv(dev);
+ struct ocelot_port *ocelot_port = &priv->port;
+ struct ocelot *ocelot = ocelot_port->ocelot;
+ int port = priv->port.index;
+ u32 rew_op = 0;
+
+ if (!static_branch_unlikely(&ocelot_fdma_enabled) &&
+ !ocelot_can_inject(ocelot, 0))
+ return NETDEV_TX_BUSY;
+
+ if (!ocelot_xmit_timestamp(ocelot, port, skb, &rew_op))
+ return NETDEV_TX_OK;
+
if (static_branch_unlikely(&ocelot_fdma_enabled)) {
ocelot_fdma_inject_frame(ocelot, port, rew_op, skb, dev);
} else {
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v3 2/3] net: mscc: ocelot: split xmit into FDMA and register injection paths
2026-02-08 22:55 [PATCH v3 0/3] net: mscc: ocelot: fix missing lock in ocelot_port_xmit() Ziyi Guo
2026-02-08 22:56 ` [PATCH v3 1/3] net: mscc: ocelot: extract ocelot_xmit_timestamp() helper Ziyi Guo
@ 2026-02-08 22:56 ` Ziyi Guo
2026-02-08 22:56 ` [PATCH v3 3/3] net: mscc: ocelot: add missing lock protection in ocelot_port_xmit_inj() Ziyi Guo
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Ziyi Guo @ 2026-02-08 22:56 UTC (permalink / raw)
To: Vladimir Oltean, Claudiu Manoil, Alexandre Belloni
Cc: UNGLinuxDriver, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev, linux-kernel, Ziyi Guo
Split ocelot_port_xmit() into two separate functions:
- ocelot_port_xmit_fdma(): handles the FDMA injection path
- ocelot_port_xmit_inj(): handles the register-based injection path
The top-level ocelot_port_xmit() now dispatches to the appropriate
function based on the ocelot_fdma_enabled static key.
This is a pure refactor with no behavioral change. Separating the two
code paths makes each one simpler and prepares for adding proper locking
to the register injection path without affecting the FDMA path.
Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>
---
drivers/net/ethernet/mscc/ocelot_net.c | 39 ++++++++++++++++++++------
1 file changed, 30 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index ef4a6c768de9..d6b0936beca2 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -571,7 +571,25 @@ static bool ocelot_xmit_timestamp(struct ocelot *ocelot, int port,
return true;
}
-static netdev_tx_t ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t ocelot_port_xmit_fdma(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct ocelot_port_private *priv = netdev_priv(dev);
+ struct ocelot_port *ocelot_port = &priv->port;
+ struct ocelot *ocelot = ocelot_port->ocelot;
+ int port = priv->port.index;
+ u32 rew_op = 0;
+
+ if (!ocelot_xmit_timestamp(ocelot, port, skb, &rew_op))
+ return NETDEV_TX_OK;
+
+ ocelot_fdma_inject_frame(ocelot, port, rew_op, skb, dev);
+
+ return NETDEV_TX_OK;
+}
+
+static netdev_tx_t ocelot_port_xmit_inj(struct sk_buff *skb,
+ struct net_device *dev)
{
struct ocelot_port_private *priv = netdev_priv(dev);
struct ocelot_port *ocelot_port = &priv->port;
@@ -579,24 +597,27 @@ static netdev_tx_t ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
int port = priv->port.index;
u32 rew_op = 0;
- if (!static_branch_unlikely(&ocelot_fdma_enabled) &&
- !ocelot_can_inject(ocelot, 0))
+ if (!ocelot_can_inject(ocelot, 0))
return NETDEV_TX_BUSY;
if (!ocelot_xmit_timestamp(ocelot, port, skb, &rew_op))
return NETDEV_TX_OK;
- if (static_branch_unlikely(&ocelot_fdma_enabled)) {
- ocelot_fdma_inject_frame(ocelot, port, rew_op, skb, dev);
- } else {
- ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb);
+ ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb);
- consume_skb(skb);
- }
+ consume_skb(skb);
return NETDEV_TX_OK;
}
+static netdev_tx_t ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ if (static_branch_unlikely(&ocelot_fdma_enabled))
+ return ocelot_port_xmit_fdma(skb, dev);
+
+ return ocelot_port_xmit_inj(skb, dev);
+}
+
enum ocelot_action_type {
OCELOT_MACT_LEARN,
OCELOT_MACT_FORGET,
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v3 3/3] net: mscc: ocelot: add missing lock protection in ocelot_port_xmit_inj()
2026-02-08 22:55 [PATCH v3 0/3] net: mscc: ocelot: fix missing lock in ocelot_port_xmit() Ziyi Guo
2026-02-08 22:56 ` [PATCH v3 1/3] net: mscc: ocelot: extract ocelot_xmit_timestamp() helper Ziyi Guo
2026-02-08 22:56 ` [PATCH v3 2/3] net: mscc: ocelot: split xmit into FDMA and register injection paths Ziyi Guo
@ 2026-02-08 22:56 ` Ziyi Guo
2026-02-09 8:56 ` [PATCH v3 0/3] net: mscc: ocelot: fix missing lock in ocelot_port_xmit() Vladimir Oltean
2026-02-13 3:10 ` patchwork-bot+netdevbpf
4 siblings, 0 replies; 6+ messages in thread
From: Ziyi Guo @ 2026-02-08 22:56 UTC (permalink / raw)
To: Vladimir Oltean, Claudiu Manoil, Alexandre Belloni
Cc: UNGLinuxDriver, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev, linux-kernel, Ziyi Guo
ocelot_port_xmit_inj() calls ocelot_can_inject() and
ocelot_port_inject_frame() without holding the injection group lock.
Both functions contain lockdep_assert_held() for the injection lock,
and the correct caller felix_port_deferred_xmit() properly acquires
the lock using ocelot_lock_inj_grp() before calling these functions.
Add ocelot_lock_inj_grp()/ocelot_unlock_inj_grp() around the register
injection path to fix the missing lock protection. The FDMA path is not
affected as it uses its own locking mechanism.
Fixes: c5e12ac3beb0 ("net: mscc: ocelot: serialize access to the injection/extraction groups")
Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>
---
drivers/net/ethernet/mscc/ocelot_net.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index d6b0936beca2..9fd8ac7e875c 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -597,14 +597,22 @@ static netdev_tx_t ocelot_port_xmit_inj(struct sk_buff *skb,
int port = priv->port.index;
u32 rew_op = 0;
- if (!ocelot_can_inject(ocelot, 0))
+ ocelot_lock_inj_grp(ocelot, 0);
+
+ if (!ocelot_can_inject(ocelot, 0)) {
+ ocelot_unlock_inj_grp(ocelot, 0);
return NETDEV_TX_BUSY;
+ }
- if (!ocelot_xmit_timestamp(ocelot, port, skb, &rew_op))
+ if (!ocelot_xmit_timestamp(ocelot, port, skb, &rew_op)) {
+ ocelot_unlock_inj_grp(ocelot, 0);
return NETDEV_TX_OK;
+ }
ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb);
+ ocelot_unlock_inj_grp(ocelot, 0);
+
consume_skb(skb);
return NETDEV_TX_OK;
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH v3 0/3] net: mscc: ocelot: fix missing lock in ocelot_port_xmit()
2026-02-08 22:55 [PATCH v3 0/3] net: mscc: ocelot: fix missing lock in ocelot_port_xmit() Ziyi Guo
` (2 preceding siblings ...)
2026-02-08 22:56 ` [PATCH v3 3/3] net: mscc: ocelot: add missing lock protection in ocelot_port_xmit_inj() Ziyi Guo
@ 2026-02-09 8:56 ` Vladimir Oltean
2026-02-13 3:10 ` patchwork-bot+netdevbpf
4 siblings, 0 replies; 6+ messages in thread
From: Vladimir Oltean @ 2026-02-09 8:56 UTC (permalink / raw)
To: Ziyi Guo
Cc: Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver, Andrew Lunn,
David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
netdev, linux-kernel
On Sun, Feb 08, 2026 at 10:55:59PM +0000, Ziyi Guo wrote:
> ocelot_port_xmit() calls ocelot_can_inject() and
> ocelot_port_inject_frame() without holding the injection group lock.
> Both functions contain lockdep_assert_held() for the injection lock,
> and the correct caller felix_port_deferred_xmit() properly acquires
> the lock using ocelot_lock_inj_grp() before calling these functions.
>
> this v3 splits the fix into a 3-patch series to separate
> refactoring from the behavioral change:
>
> 1/3: Extract the PTP timestamp handling into an ocelot_xmit_timestamp()
> helper so the logic isn't duplicated when the function is split.
>
> 2/3: Split ocelot_port_xmit() into ocelot_port_xmit_fdma() and
> ocelot_port_xmit_inj(), keeping the FDMA and register injection
> code paths fully separate.
>
> 3/3: Add ocelot_lock_inj_grp()/ocelot_unlock_inj_grp() in
> ocelot_port_xmit_inj() to fix the missing lock protection.
>
> Patches 1-2 are pure refactors with no behavioral change.
> Patch 3 is the actual bug fix.
>
> v3:
> - Split into 3-patch series per Vladimir's review
> - Separate FDMA and register injection paths into distinct functions
> v2:
> - Added Fixes tag
> v1:
> - Initial submission
For the series:
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
I see you didn't specify the target tree name in the git subject prefix
(see Documentation/process/maintainer-netdev.rst). For the future,
please do so. This patch set should go to 'net'.
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH v3 0/3] net: mscc: ocelot: fix missing lock in ocelot_port_xmit()
2026-02-08 22:55 [PATCH v3 0/3] net: mscc: ocelot: fix missing lock in ocelot_port_xmit() Ziyi Guo
` (3 preceding siblings ...)
2026-02-09 8:56 ` [PATCH v3 0/3] net: mscc: ocelot: fix missing lock in ocelot_port_xmit() Vladimir Oltean
@ 2026-02-13 3:10 ` patchwork-bot+netdevbpf
4 siblings, 0 replies; 6+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-02-13 3:10 UTC (permalink / raw)
To: Ziyi Guo
Cc: vladimir.oltean, claudiu.manoil, alexandre.belloni,
UNGLinuxDriver, andrew+netdev, davem, edumazet, kuba, pabeni,
netdev, linux-kernel
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Sun, 8 Feb 2026 22:55:59 +0000 you wrote:
> ocelot_port_xmit() calls ocelot_can_inject() and
> ocelot_port_inject_frame() without holding the injection group lock.
> Both functions contain lockdep_assert_held() for the injection lock,
> and the correct caller felix_port_deferred_xmit() properly acquires
> the lock using ocelot_lock_inj_grp() before calling these functions.
>
> this v3 splits the fix into a 3-patch series to separate
> refactoring from the behavioral change:
>
> [...]
Here is the summary with links:
- [v3,1/3] net: mscc: ocelot: extract ocelot_xmit_timestamp() helper
https://git.kernel.org/netdev/net/c/29372f07f796
- [v3,2/3] net: mscc: ocelot: split xmit into FDMA and register injection paths
https://git.kernel.org/netdev/net/c/47f79b20e7fb
- [v3,3/3] net: mscc: ocelot: add missing lock protection in ocelot_port_xmit_inj()
https://git.kernel.org/netdev/net/c/026f6513c588
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 6+ messages in thread