From: netdev-bot+sashiko@kernel.org
To: niklas.soderlund+renesas@ragnatech.se
Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
geert+renesas@glider.be, magnus.damm@gmail.com,
richardcochran@gmail.com, andrew+netdev@lunn.ch,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, vadim.fedorenko@linux.dev,
sergei.shtylyov@gmail.com, linux-renesas-soc@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org
Subject: Re: [PATCH net-next v3 06/10] net: ethernet: ravb: Replace gPTP flags with callbacks
Date: Mon, 07 Sep 2026 02:48:34 +0000 [thread overview]
Message-ID: <178874931491.219967.7169661491703967460@kernel.org> (raw)
In-Reply-To: <20260902084703.3228504-7-niklas.soderlund+renesas@ragnatech.se>
Thank you for your contribution! Sashiko AI review found 5 potential
issue(s) to consider:
Critical: 1 · High: 2 · Medium: 2 · Low: 0 (1)
- [Critical] ravb_get_ts_info() unconditionally dereferences
priv->ptp.clock via ptp_clock_index() whenever the hardware table…
- [High] For Gen3 (and Gen4, which shares ravb_gen3_ptp_info in this
commit) the PTP clock is registered by info->ptp->ndev_open()…
- [High] ravb_ptp_stop() does not clear priv->ptp.clock, so the stop
callback is not idempotent: a second invocation without an intervening…
- [Medium] ravb_dmac_init() now returns the error from
info->ptp->dmac_start() (ravb_ptp_init() for Gen2/RZ-V2M), creating a…
- [Medium] The commit message presents the change as a mechanical
refactor ("replacing the flags for Gen2 behavior (info->gptp) and Gen3…
Pre-existing issues:
- [Low] In ravb_ptp_init() the GTI load sequence requests loading with
GCCR_LTI (0x8) but the following wait — commented "Wait for GIT…
--
net: ethernet: ravb: Replace gPTP flags with callbacks
The gPTP behavior flags info->gptp (Gen2) and info->ccc_gac (Gen3) are
replaced by a new struct ravb_gptp_info holding callbacks for config mode
entry, DMAC start/stop and ndev open/close. Each hardware info table now
points at a per-generation callback table. This prepares for adding Gen4
support.
> diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
> index 0c122a8158409..6603f90b19e15 100644
> --- a/drivers/net/ethernet/renesas/ravb.h
> +++ b/drivers/net/ethernet/renesas/ravb.h
[ ... ]
> diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
> index 7c7b3ac81e5d6..5d5b9c0e2f450 100644
> --- a/drivers/net/ethernet/renesas/ravb_main.c
> +++ b/drivers/net/ethernet/renesas/ravb_main.c
> @@ -712,8 +712,8 @@ static int ravb_dmac_init(struct net_device *ndev)
> return error;
>
> /* Initialise PTP Clock driver */
> - if (info->gptp)
> - ravb_ptp_init(ndev);
> + if (info->ptp && info->ptp->dmac_start)
> + return info->ptp->dmac_start(ndev);
>
> return 0;
> }
[Severity: Medium]
Can this leak the descriptor rings and page pools?
For Gen2 and RZ/V2M, .dmac_start is ravb_ptp_init(), which can fail with
the PTR_ERR() from ptp_clock_register(). That error is now returned from
ravb_dmac_init() after info->dmac_init() already allocated the page pools,
rx_buffers, tx_skb arrays, aligned TX buffers and the coherent descriptor
rings, and after the DMAC was switched to CCC_OPC_OPERATION.
In ravb_open() that error goes to out_set_reset:
out_set_reset:
ravb_set_opmode(ndev, CCC_OPC_RESET);
so ravb_stop_dma() is skipped and ravb_ring_free() is never called. Since
ndo_open failed, ravb_close() will not run either, and the next open
re-runs ravb_ring_init() which overwrites priv->rx_pool[], priv->rx_buffers[],
priv->tx_skb[], priv->rx_ring[] and priv->tx_ring[] unconditionally, so the
previous allocations can never be freed.
The other two callers see the same new late failure. ravb_set_ringparam()
returns the error with the netdev still detached and the DMAC in operation
mode, and ravb_tx_timeout_work() returns with all TX queues stopped, which
seems to contradict its own comment:
/* If ravb_dmac_init() fails, descriptors are freed. So, this
* should return here to avoid re-enabling the TX and RX in
* ravb_emac_init().
*/
Would it make sense to roll back inside ravb_dmac_init() when the gPTP start
callback fails (stop the DMA, return to CONFIG mode and free the rings) so
that the documented post-condition of a failed ravb_dmac_init() still holds
for every generation?
[Severity: Medium]
The commit message describes this as replacing "the flags for Gen2 behavior
(info->gptp) and Gen3 behavior (info->ccc_gac) with callbacks", which reads
as a mechanical refactor.
The patch also changes failure behaviour. Before, both call sites discarded
the ravb_ptp_init() return value:
if (info->gptp)
ravb_ptp_init(ndev);
return 0;
Now ravb_dmac_init() propagates it for Gen2/RZ-V2M, and ravb_open() aborts
when the Gen3/Gen4 .ndev_open callback fails, so a PTP clock registration
failure turns into a failed ndo_open (and a failed ethtool ring resize or
TX timeout recovery) where it previously left the interface fully usable.
Only the v2 changelog below the '---' line mentions this ("Handle error from
starting the PTP clock"), and that text is dropped when the patch is applied.
Could the commit message itself mention the behaviour change?
> @@ -1124,8 +1124,8 @@ static int ravb_stop_dma(struct net_device *ndev)
> }
>
> /* Stop PTP Clock driver */
> - if (info->gptp)
> - ravb_ptp_stop(ndev);
> + if (info->ptp && info->ptp->dmac_stop)
> + info->ptp->dmac_stop(ndev);
>
> /* Stop AVB-DMAC process */
> return ravb_set_opmode(ndev, CCC_OPC_CONFIG);
[Severity: High]
Can this end up calling ptp_clock_unregister() twice on the same clock?
ravb_ptp_stop() no longer clears priv->ptp.clock:
drivers/net/ethernet/renesas/ravb_ptp.c:ravb_ptp_stop() {
...
if (priv->ptp.clock)
ptp_clock_unregister(priv->ptp.clock);
}
so the callback is not idempotent. With .dmac_stop = ravb_ptp_stop for Gen2
and RZ/V2M, ravb_stop_dma() is reachable from ravb_close(),
ravb_set_ringparam(), ravb_tx_timeout_work() and the ravb_open() error path,
and two stops with no ravb_ptp_init() in between look possible:
ethtool -G eth0 rx 4096
ravb_set_ringparam()
ravb_stop_dma()
info->ptp->dmac_stop() -> ravb_ptp_stop() -> ptp_clock_unregister()
priv->ptp.clock left dangling
ravb_dmac_init() -> fails (ravb_ring_init() -ENOMEM, or
ravb_set_opmode() timeout), so dmac_start
and ravb_ptp_init() never run
return error -> netdev still running
ip link set eth0 down
ravb_close()
ravb_stop_dma()
info->ptp->dmac_stop() -> ravb_ptp_stop()
if (priv->ptp.clock) still true
ptp_clock_unregister() on freed memory
The same interleaving looks reachable through ravb_tx_timeout_work(), where a
successful ravb_stop_dma() is followed by a failing ravb_dmac_init() and
'goto out_unlock' with the interface still up.
The xchg(&priv->ptp.clock, NULL) that used to make this idempotent was
removed by the earlier series commit "net: ethernet: ravb: Propagate error
from ptp_clock_register()", and ravb_ptp_stop() is still non-idempotent at
the end of the series. Should priv->ptp.clock be cleared in
ravb_ptp_stop()?
> @@ -1774,7 +1774,7 @@ static int ravb_get_ts_info(struct net_device *ndev,
> struct ravb_private *priv = netdev_priv(ndev);
> const struct ravb_hw_info *hw_info = priv->info;
>
> - if (hw_info->gptp || hw_info->ccc_gac) {
> + if (hw_info->ptp) {
> info->so_timestamping =
[Severity: Critical]
Is this guard sufficient for the ptp_clock_index() call in the body?
hw_info->ptp is a static hardware capability, but the body still does:
info->phc_index = ptp_clock_index(priv->ptp.clock);
and with CONFIG_PTP_1588_CLOCK enabled that is:
drivers/ptp/ptp_clock.c:ptp_clock_index() {
return ptp->index;
}
priv->ptp.clock is NULL until the interface is opened (Gen3/Gen4 register in
the .ndev_open callback, Gen2/RZ-V2M in .dmac_start), and it is left dangling
after ravb_ptp_stop() because that function no longer clears it. So:
ethtool -T eth0 # device probed, never brought up
ravb_get_ts_info()
hw_info->ptp != NULL # all ravb tables set .ptp
ptp_clock_index(NULL) # NULL dereference
ip link set eth0 up; ip link set eth0 down; ethtool -T eth0
ravb_get_ts_info()
ptp_clock_index(<freed ptp_clock>) # value returned in phc_index
ETHTOOL_GET_TS_INFO is listed in net/ethtool/ioctl.c among the commands that
fall through before the ns_capable(CAP_NET_ADMIN) check, so this is reachable
by an unprivileged local user.
This is still broken at the end of the series, where ravb_get_ts_info() calls
hw_info->ptp->clock_index() and ravb_gen2_ptp_clock_index() is just
'return ptp_clock_index(priv->ptp.clock);'. The cached priv->ptp.phc_index
(reset to -1 in ravb_ptp_stop()) plus the xchg() clearing of the pointer that
used to make this safe were removed by the earlier series commit "net:
ethernet: ravb: Propagate error from ptp_clock_register()". Should the
phc_index only be reported when a clock is actually registered?
[ ... ]
> @@ -1967,8 +1957,11 @@ static int ravb_open(struct net_device *ndev)
> ravb_emac_init(ndev);
>
> /* Initialise PTP Clock driver */
> - if (info->ccc_gac)
> - ravb_ptp_init(ndev);
> + if (info->ptp && info->ptp->ndev_open) {
> + error = info->ptp->ndev_open(ndev);
> + if (error)
> + goto out_ptp_stop;
> + }
>
> /* PHY control start */
> error = ravb_phy_start(ndev);
[Severity: High]
Does the out_ptp_stop label still stop the PTP clock for Gen3 and Gen4?
For ravb_gen3_ptp_info (which ravb_gen4_hw_info also uses in this commit) the
clock is registered from .ndev_open = ravb_ptp_init, and the only teardown is
.ndev_close = ravb_ptp_stop. The label reachable from here is:
out_ptp_stop:
ravb_stop_dma(ndev);
out_set_reset:
ravb_set_opmode(ndev, CCC_OPC_RESET);
and ravb_stop_dma() only calls dmac_stop:
if (info->ptp && info->ptp->dmac_stop)
info->ptp->dmac_stop(ndev);
.dmac_stop is NULL in ravb_gen3_ptp_info, so ravb_ptp_stop() never runs. If
ravb_phy_start() fails after a successful ndev_open, ndo_open returns an error
with the PHC still registered while the DMAC is forced to CCC_OPC_RESET and
the device is runtime suspended. ndo_stop is not called for a failed open, so
nothing ever calls ndev_close for that registration, and each retried open
re-registers over priv->ptp.clock.
ravb_remove() does no PTP teardown:
of_node_put(priv->of_gptp);
reset_control_assert(priv->rstc);
free_netdev(ndev);
Since ptp_clock_register() keeps the caller's struct ptp_clock_info pointer
(priv->ptp.info, inside the netdev private data), can the orphaned /dev/ptpN
outlive free_netdev() and dereference freed memory on a later ioctl?
The symmetric teardown existed at the series baseline as
'if (info->gptp || info->ccc_gac) ravb_ptp_stop(ndev);' at this label and was
dropped by the earlier series commit "net: ethernet: ravb: Simplify gPTP start
and stop"; the label is still just ravb_stop_dma() at the end of the series.
Should the open error path call info->ptp->ndev_close()? The failing
ndev_open case itself is already cleaned up inside ravb_ptp_init().
[ ... ]
One more observation, unrelated to the diff itself:
[Severity: Low]
This isn't a bug introduced by this patch, but the GTI load sequence in
ravb_ptp_init() waits on the wrong field:
drivers/net/ethernet/renesas/ravb_ptp.c:ravb_ptp_init() {
...
/* Request GTI loading. */
ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI);
/* Wait for GIT loading to complete. */
ravb_wait(ndev, GCCR, GCCR_TCR, GCCR_TCR_NOREQ);
}
GCCR_TCR and GCCR_LTI are distinct fields:
drivers/net/ethernet/renesas/ravb.h:
GCCR_TCR = 0x00000003,
...
GCCR_LTI = 0x00000008,
so the wait cannot observe LTI completion, and ravb_wait()'s return value is
discarded as well. The worst effect I can see is a transient unloaded timer
increment or an -EBUSY from a very early ravb_ptp_adjfine(), which treats a
set GCCR_LTI as busy.
The pre-existing baseline had no LTI poll at all in ravb_set_gti(); the
misleading comment came from the earlier series commit "net: ethernet: ravb:
Move programming of gPTP timer interval", whose message also states that the
init function waits for the interval programming to be acknowledged. Should
the wait poll GCCR_LTI and check the result?
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260902084703.3228504-1-niklas.soderlund%2Brenesas%40ragnatech.se
next prev parent reply other threads:[~2026-09-07 2:48 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-02 8:46 [PATCH net-next v3 00/10] ravb: Add gPTP support for Gen4 Niklas Söderlund
2026-09-02 8:46 ` [PATCH net-next v3 01/10] net: ethernet: ravb: Remove gPTP control from WoL setup and restore Niklas Söderlund
2026-09-03 8:47 ` sashiko-bot
2026-09-03 11:11 ` Niklas Söderlund
2026-09-07 2:48 ` netdev-bot+sashiko
2026-09-02 8:46 ` [PATCH net-next v3 02/10] net: ethernet: ravb: Move programming of gPTP timer interval Niklas Söderlund
2026-09-03 8:47 ` sashiko-bot
2026-09-07 2:48 ` netdev-bot+sashiko
2026-09-02 8:46 ` [PATCH net-next v3 03/10] net: ethernet: ravb: Simplify gPTP start and stop Niklas Söderlund
2026-09-03 8:47 ` sashiko-bot
2026-09-07 2:48 ` netdev-bot+sashiko
2026-09-02 8:46 ` [PATCH net-next v3 04/10] net: ethernet: ravb: Remove redundant argument to ravb_ptp_init() Niklas Söderlund
2026-09-02 8:46 ` [PATCH net-next v3 05/10] net: ethernet: ravb: Propagate error from ptp_clock_register() Niklas Söderlund
2026-09-03 8:47 ` sashiko-bot
2026-09-03 11:35 ` Niklas Söderlund
2026-09-07 2:48 ` netdev-bot+sashiko
2026-09-02 8:46 ` [PATCH net-next v3 06/10] net: ethernet: ravb: Replace gPTP flags with callbacks Niklas Söderlund
2026-09-03 8:47 ` sashiko-bot
2026-09-07 2:48 ` netdev-bot+sashiko [this message]
2026-09-02 8:47 ` [PATCH net-next v3 07/10] net: ethernet: ravb: Add callback for gPTP probe Niklas Söderlund
2026-09-03 8:47 ` sashiko-bot
2026-09-07 2:48 ` netdev-bot+sashiko
2026-09-02 8:47 ` [PATCH net-next v3 08/10] net: ethernet: ravb: Add callback for gPTP clock index Niklas Söderlund
2026-09-03 8:47 ` sashiko-bot
2026-09-07 2:48 ` netdev-bot+sashiko
2026-09-02 8:47 ` [PATCH net-next v3 09/10] dt-bindings: net: renesas,etheravb: Add optional gPTP phandle for Gen4 Niklas Söderlund
2026-09-07 2:48 ` netdev-bot+sashiko
2026-09-02 8:47 ` [PATCH net-next v3 10/10] net: ethernet: ravb: Add gPTP support " Niklas Söderlund
2026-09-03 8:48 ` sashiko-bot
2026-09-07 2:48 ` netdev-bot+sashiko
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=178874931491.219967.7169661491703967460@kernel.org \
--to=netdev-bot+sashiko@kernel.org \
--cc=andrew+netdev@lunn.ch \
--cc=conor+dt@kernel.org \
--cc=davem@davemloft.net \
--cc=devicetree@vger.kernel.org \
--cc=edumazet@google.com \
--cc=geert+renesas@glider.be \
--cc=krzk+dt@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-renesas-soc@vger.kernel.org \
--cc=magnus.damm@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=niklas.soderlund+renesas@ragnatech.se \
--cc=pabeni@redhat.com \
--cc=richardcochran@gmail.com \
--cc=robh@kernel.org \
--cc=sergei.shtylyov@gmail.com \
--cc=vadim.fedorenko@linux.dev \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox