From: Jacob Keller <jacob.e.keller@intel.com>
To: <netdev-bot+sashiko@kernel.org>, <anthony.l.nguyen@intel.com>
Cc: <davem@davemloft.net>, <kuba@kernel.org>, <pabeni@redhat.com>,
<edumazet@kernel.org>, <andrew+netdev@lunn.ch>,
<netdev@vger.kernel.org>, <maciej.machnikowski@intel.com>,
<przemyslaw.korba@intel.com>, <grzegorz.nitka@intel.com>,
<sergey.temerkhanov@intel.com>, <arkadiusz.kubalewski@intel.com>,
<poros@redhat.com>, <richardcochran@gmail.com>,
<horms@kernel.org>, <pmenzel@molgen.mpg.de>,
<aleksandr.loktionov@intel.com>, <alexander.nowlin@intel.com>
Subject: Re: [PATCH net v2 01/15] ice: fix removal of PTP timestamp tracker during reset
Date: Tue, 13 Oct 2026 14:31:29 -0700 [thread overview]
Message-ID: <50484cfe-7451-4707-8f23-165a6c85f4f0@intel.com> (raw)
In-Reply-To: <179184691805.434549.1970305171129280416@kernel.org>
On 10/12/2026 4:15 PM, netdev-bot+sashiko@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 4 potential
> issue(s) to consider.
>
> Critical: 0 · High: 1 · Medium: 3 (4) · Low: 0
>
> If you believe none of the issues are legitimate, please reply to each
> issue of Medium severity or higher and explain why the AI is wrong.
> If any of them are legitimate and you plan to respin, please let patchwork
> know by including "pw-bot: cr" as a separate line at the end of your reply
> (one such reply per series is enough).
>
> - [High] The new non-READY (ERROR/RESETTING) branch of ice_ptp_release()
> destroys the worker too early.
> - [Medium] The patch removes ice_ptp_release_tx_tracker() from
> ice_ptp_prepare_for_reset() and puts nothing in its place.
> - [Medium] At this commit, when ice_ptp_init_work() fails, the code now
> jumps to err_clean_pf.
> - [Medium] Now that the Tx tracker survives CORE/GLOBAL/EMP resets, its
> per-index tstamps[idx].cached_tstamp and last_ll_ts_idx_read are never…
>
> Pre-existing issues:
> - [Medium] The non-READY branch of ice_ptp_release() tears everything
> down: kworker, clock, list_del via ice_ptp_cleanup_pf(), the Tx…
> - [Medium] At this commit, ice_ptp_flush_all_tx_tracker(),
> ice_ptp_restart_all_phy() and ice_ptp_prepare_rebuild_sec() walk…
> - [Medium] On E825, ice_ptp_setup_pf() sets this port's bit in the
> control PF's shared tx_refclks[phy][tx_clk] map.
> - [Medium] Neither the ice_ptp_init() error unwind (after
> ice_ptp_reset_phy_timestamping() and ice_ptp_cfg_tx_interrupt()) nor…
>
> --
>
> ice: fix removal of PTP timestamp tracker during reset
>
> This commit stops releasing the PTP Tx timestamp tracker in
> ice_ptp_prepare_for_reset(), so timestamping can resume after CORE, GLOBAL
> or EMP resets. It reorders ice_ptp_init() so the tracker is allocated
> before the port is added to the port list, and the tracker is released on
> error. ice_ptp_release() now cancels the kworker and releases the tracker
> when PTP is not in the READY state.
>
> Closes: https://sashiko.dev/#/patchset/20260821-jk-e825c-minimized-fixes-v1-0-9d0731eb4858%40intel.com?part=8
> Closes: https://lore.kernel.org/netdev/20260916011213.1632286-1-kuba@kernel.org/
>
>> diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
>> index eaec36ab6ae3f..fe21cee4f9dee 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_ptp.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
>> @@ -2939,8 +2939,6 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
>> if (ice_pf_src_tmr_owned(pf) && hw->mac_type == ICE_MAC_GENERIC_3K_E825)
>> ice_ptp_prepare_rebuild_sec(pf, false, reset_type);
>>
>> - ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
>> -
>
> [Severity: Medium]
>
> With this call removed, nothing clears tx->init or calls synchronize_irq()
> before a CORE, GLOBAL or EMP reset. Is that intended?
>
Yes, this was intended.
> The Tx timestamp paths check only tx->init and tx->calibrating. They never
> check ptp->state. Suppose ice_ptp_rebuild() fails:
>
> ice_ptp_rebuild()
> err:
> ptp->state = ICE_PTP_ERROR;
>
> ice_rebuild() still calls ice_ptp_restore_timestamp_mode()
> unconditionally, and that re-enables the Tx timestamp interrupt. After
> that, ice_tstamp()->ice_ptp_request_ts() only checks:
>
> if (!ice_ptp_is_tx_tracker_up(tx)) {
>
> So slots are still handed out (skb_get() plus SKBTX_IN_PROGRESS) against a
> PHC that isn't running. In the ERROR state cached_phc_jiffies is never
> refreshed, so ice_ptp_extend_40b_ts() would discard the result. Before
> this patch, these requests were refused and counted in
> tx_hwtstamp_skipped.
>
> During the reset window itself, ice_ll_ts_intr() only checks tx->init:
>
> if (tx->init) {
> ice_ptp_complete_tx_single_tstamp(tx);
>
> The E810 path in ice_ptp_ts_irq() also checks ice_pf_state_is_nominal().
> Can the LL proxy registers now be accessed in the middle of a reset?
>
I am not certain any of this actually results in a real issue. We could
add a check to prevent new timestamp requests while the state is
non-ready I suppose.. But I don't know if anything here actually fails.
The messaging could be improved. In practice I am unsure if the driver
actually *can* timestamp here since it would have stopped the traffic
queues during queisce before reset.
> The commit message doesn't mention this change in behaviour. Later patches
> in the series only add link_up and calibrating gating, so tx->init still
> stays set across the reset.
>
Yes, tx->init stays valid, because we need to keep the tracker and
removing it was problematic. Checking the reset state may make sense but
I am not convinced this is a real visible problem.
> [Severity: Medium]
>
> The tracker now survives the reset, so tstamps[idx].cached_tstamp and
> last_ll_ts_idx_read are no longer reset. The E810 PHY timestamp memory is
> still reset. Can the two get out of sync?
>
> On rebuild, ice_ptp_rebuild_owner()->ice_ptp_flush_all_tx_tracker()->
> ice_ptp_flush_tx_tracker() calls ice_clear_phy_tstamp() for every in_use
> index, because tstamp_ready is all ones on E810.
> ice_clear_phy_tstamp_e810() then writes 0 to both halves:
>
> err = ice_write_phy_reg_e810(hw, lo_addr, 0);
> ...
> err = ice_write_phy_reg_e810(hw, hi_addr, 0);
>
> E810 has no ready bitmap. It detects a new capture by checking raw_tstamp
> != cached_tstamp. After the reset, a reused index that hasn't captured yet
> reads 0, and 0 differs from the stale cached value.
>
> In ice_ptp_process_tx_tstamp(), the missing VALID bit makes it drop the
> timestamp and release the slot. Because raw is 0, cached_tstamp isn't
> updated, so the later real capture could be credited to the next request
> that uses that index.
>
This looks like a preexisting issue that we should clear the cached
value when writing the PHY registers for E810. This should be fixed, but
IMO should not block this series.
> ice_ptp_complete_tx_single_tstamp() has no VALID check:
>
> if (raw_tstamp == tx->tstamps[idx].cached_tstamp)
> return;
>
> tx->tstamps[idx].cached_tstamp = raw_tstamp;
> clear_bit(idx, tx->in_use);
>
> It would then pass ice_ptp_extend_40b_ts(pf, 0) to skb_tstamp_tx().
>
This also looks like a preexisting issue in the low latency path that
should have been checking valid bits.
> Before 7a25fe5cd5fb the tracker was reallocated with zeroed cached values,
> so software and hardware stayed in sync. This is still present at the end
> of the series.
Before this series, timestamping stopped permanently after a device reset.
>
>> /* Disable periodic outputs */
>> ice_ptp_disable_all_perout(pf);
>>
>> @@ -3347,13 +3345,13 @@ void ice_ptp_init(struct ice_pf *pf)
>> }
>> }
>>
>> - err = ice_ptp_setup_pf(pf);
>> + err = ice_ptp_init_port(pf, &ptp->port);
>> if (err)
>> - goto err_exit;
>> + goto err_destroy_ps_lock;
>>
>> - err = ice_ptp_init_port(pf, &ptp->port);
>> + err = ice_ptp_setup_pf(pf);
>> if (err)
>> - goto err_clean_pf;
>> + goto err_release_tx_tracker;
>>
>> /* Start the PHY timestamping block */
>> ice_ptp_reset_phy_timestamping(pf);
>
> [Severity: Medium]
>
> This isn't a bug introduced by this patch, but neither the ice_ptp_init()
> error unwind nor the non-READY branch of ice_ptp_release() puts the
> hardware back into a quiet state.
>
True. These are *error cleanup* flows which are just trying to do their
best to cleanup and avoid leaks.
> ice_ptp_reset_phy_timestamping() and ice_ptp_cfg_tx_interrupt() run before
> ice_ptp_init_work(). If ice_ptp_init_work() then fails, the unwind never
> calls ice_ptp_disable_timestamp_mode(), ice_ptp_port_phy_stop() or the
> perout/extts disables.
>
> Can OICR TSYN_TX, PHY timestamping and the SDP outputs stay armed after the
> software state has been torn down?
Presumably yes if you fail at exactly the right way. But the software
really has no way to know which parts would need to be torn down, and
whether it even has access. Should we balloon the error handling logic
to try and detect and cleanup every possible state here? I don't think
thats helpful.
>
> [ ... ]
>
>> @@ -3365,14 +3363,17 @@ void ice_ptp_init(struct ice_pf *pf)
>>
>> err = ice_ptp_init_work(pf, ptp);
>> if (err)
>> - goto err_exit;
>> + goto err_clean_pf;
>
> [Severity: Medium]
>
> When ice_ptp_init_work() fails, this path now frees the Tx tracker and
> destroys ps_lock. However, ptp->state was set just above:
>
> ptp->state = ICE_PTP_READY;
>
> err = ice_ptp_init_work(pf, ptp);
> if (err)
> goto err_clean_pf;
>
> The PHC is also still registered at this point. Could ice_ptp_link_change(),
> ice_ptp_queue_work() or the PHC callbacks touch the freed tracker or the
> destroyed mutex in this window? One example is
> ice_ptp_reset_cached_phctime()->ice_ptp_mark_tx_tracker_stale().
>
> The NULL kworker exposure while READY was already there before. Later in
> the series, ice_ptp_init() creates the kworker earlier and sets
> ICE_PTP_READY only after ice_ptp_init_work() succeeds, which appears to
> close this. At this commit the window is still open.
>
This has been incredibly frustrating, as every time I change the order
here I end up with some other complaint about teardown order :\
We should be cleaning up the PTP clock first, but this is complicated by
the fact that each PF unloads independently and only the clock owner PF
actually has a clock. This outline does imply that the paths could
access the kworker while the port is still in the list, so ya I guess
this really should be afterwards.
The worker thread does appear to check the PTP state so I guess
reordering it would be safe.
>>
>> dev_info(ice_pf_to_dev(pf), "PTP init successful\n");
>> return;
>>
>> err_clean_pf:
>> - mutex_destroy(&ptp->port.ps_lock);
>> ice_ptp_cleanup_pf(pf);
>
> [Severity: Medium]
>
> This is a pre-existing issue, but on E825 ice_ptp_setup_pf() sets this
> port's bit in the control PF's shared map:
>
> set_bit(port_num,
> &ctrl_ptp->tx_refclks[phy][pf->ptp.port.tx_clk]);
>
> ice_ptp_cleanup_pf() only does list_del() and never clears that bit. After
> this error path, or after an unbind, would ice_txclk_any_port_uses() still
> count this port as a user of the reference clock?
>
This looks like an issue for the developer of the refclk code to fix.
>> +err_release_tx_tracker:
>> + ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
>> +err_destroy_ps_lock:
>> + mutex_destroy(&ptp->port.ps_lock);
>> err_exit:
>
> [ ... ]
>
>> @@ -3399,12 +3400,20 @@ void ice_ptp_release(struct ice_pf *pf)
>> return;
>>
>> if (pf->ptp.state != ICE_PTP_READY) {
>> - mutex_destroy(&pf->ptp.port.ps_lock);
>> - ice_ptp_cleanup_pf(pf);
>> + if (pf->ptp.kworker) {
>> + kthread_cancel_delayed_work_sync(&pf->ptp.work);
>> + if (pf->hw.mac_type == ICE_MAC_GENERIC)
>> + kthread_cancel_delayed_work_sync(&pf->ptp.port.ov_work);
>> + kthread_destroy_worker(pf->ptp.kworker);
>> + pf->ptp.kworker = NULL;
>> + }
>
> [Severity: High]
>
> The worker is destroyed here and pf->ptp.kworker is set to NULL. The PHC is
> only unregistered further down, and the port stays on
> adapter->ports.ports until ice_ptp_cleanup_pf() runs. Can anything still
> reach this worker in between?
>
> On ICE_MAC_GENERIC, ice_ptp_settime64() calls ice_ptp_restart_all_phy()
> without checking ptp->state. ice_ptp_adjtime() does the same through its
> non-atomic path. ice_ptp_restart_all_phy() walks the list without
> ports.lock:
>
> list_for_each(entry, &pf->adapter->ports.ports) {
> ...
> if (port->link_up)
> ice_ptp_port_phy_restart(port);
> }
>
> ice_ptp_port_phy_restart() then does:
>
> case ICE_MAC_GENERIC:
> kthread_cancel_delayed_work_sync(&ptp_port->ov_work);
> ...
> kthread_queue_delayed_work(pf->ptp.kworker, &ptp_port->ov_work,
> 0);
>
> Here pf is the releasing PF. That covers the releasing PF's own port, and
> also its port when it is a peer and the owner PF is the one calling
> settime.
>
> ice_ptp_reset_cached_phctime() also queues on pf->ptp.kworker when
> ICE_CFG_BUSY is set, with no NULL or state check.
>
> Before this patch the non-READY branch leaked the worker rather than
> freeing it, so this NULL dereference or use-after-free of the
> kthread_worker looks new. It can be hit if a PF in ERROR or RESETTING
> state is unbound while userspace calls clock_settime() on the owner PHC.
>
> Could the clock be unregistered and the port removed from the list before
> the worker is destroyed? The commit message already describes that
> ordering for ps_lock. The ordering here is unchanged at the end of the
> series.
Yea, I guess we need to do the cleanup first and then teardown the
kworkers.. This has been quite frustrating because I believe I got other
complaints about order when trying to do that way before :\ Hopefully we
can find something that works...
>
>> if (pf->ptp.clock) {
>> ptp_clock_unregister(pf->ptp.clock);
>> pf->ptp.clock = NULL;
>> }
>> + ice_ptp_cleanup_pf(pf);
>> + ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
>
> [Severity: Medium]
>
> This is a pre-existing issue, but three functions walk
> adapter->ports.ports without ports.lock: ice_ptp_flush_all_tx_tracker(),
> ice_ptp_restart_all_phy() and ice_ptp_prepare_rebuild_sec(). For example:
>
> list_for_each_entry(port, &pf->adapter->ports.ports, list_node)
> ice_ptp_flush_tx_tracker(ptp_port_to_pf(port), &port->tx);
>
> Meanwhile ice_ptp_cleanup_pf() unlinks the port under the lock, and
> ice_ptp_release_tx_tracker() then frees the tracker. Trackers now stay
> allocated across CORE/GLOBAL resets, so the owner's rebuild-time flush
> works on live peer trackers. Can one of these walkers race with this
> teardown?
>
> A later patch in this series, "ice: use reference counting and SRCU for
> PTP port access", converts these walkers to SRCU with kref and appears to
> close this race.
Yes. I tried to have that patch first but it got far too many complaints
about *this* issue, so I re-ordered the series.
>
>> + mutex_destroy(&pf->ptp.port.ps_lock);
>> return;
>> }
>
> [Severity: Medium]
>
> This isn't a bug introduced by this patch, but this branch tears
> everything down and returns without setting pf->ptp.state to
> ICE_PTP_UNINIT. If ice_ptp_release() runs again before ice_ptp_init()
> resets the state, would ice_ptp_cleanup_pf() call list_del() on a node
> that already holds LIST_POISON pointers?
>
Another on the pile of possible pre-existing issues... :D
> One possible sequence:
>
> 1. devlink reinit_down runs while PTP is in ERROR or RESETTING, which goes
> through ice_unload()->ice_ptp_release().
> 2. reinit_up fails before ice_load().
> 3. ice_remove()->ice_unload()->ice_deinit_features()->ice_ptp_release()
> runs again.
>
> The old branch had the same list_del() without a state change, and the end
> of the series still doesn't set ICE_PTP_UNINIT here.
>
Problem is that I am not sure if setting to UNINIT is totally correct
here :\ Of course the original design/logic here was that this is part
of driver remove and not something that would be re-triggered such as
via devlink.
next prev parent reply other threads:[~2026-10-13 21:31 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-08 21:55 [PATCH net v2 00/15][pull request] ice: E82x: timestamp processing logic fixes Tony Nguyen
2026-10-08 21:55 ` [PATCH net v2 01/15] ice: fix removal of PTP timestamp tracker during reset Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 21:31 ` Jacob Keller [this message]
2026-10-08 21:55 ` [PATCH net v2 02/15] ice: use reference counting and SRCU for PTP port access Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 21:41 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 03/15] ice: fix PHY port restart serialization Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 21:43 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 04/15] ice: set in_use only after preparing Tx timestamp index Tony Nguyen
2026-10-08 21:56 ` [PATCH net v2 05/15] ice: call PTP link change only from link events Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 21:58 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 06/15] ice: E822: keep Tx timestamps disabled during offset calibration Tony Nguyen
2026-10-08 21:56 ` [PATCH net v2 07/15] ice: E822: cancel offset verification work during reset preparation Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:07 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 08/15] ice: E825: stop clearing PHY_REG_TX_OFFSET_READY Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:08 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 09/15] ice: E825: clear PHY_REG_TX_MEMORY_STATUS prior to soft reset Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:11 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 10/15] ice: E825: perform a soft reset when starting the PHY timer Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:32 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 11/15] ice: wait for in-flight Tx timestamps before flushing the tracker Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:39 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 12/15] ice: keep Tx timestamp slots tracked until completion or timeout Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:44 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 13/15] ice: skip reading Tx ready bitmap on ports with no timestamps Tony Nguyen
2026-10-08 21:56 ` [PATCH net v2 14/15] ice: don't clear in_use until HW clears ready bitmap Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:59 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 15/15] ice: Recalibrate PHY after settime64 on E825-C Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 23:04 ` Jacob Keller
2026-10-14 0:59 ` Jacob Keller
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=50484cfe-7451-4707-8f23-165a6c85f4f0@intel.com \
--to=jacob.e.keller@intel.com \
--cc=aleksandr.loktionov@intel.com \
--cc=alexander.nowlin@intel.com \
--cc=andrew+netdev@lunn.ch \
--cc=anthony.l.nguyen@intel.com \
--cc=arkadiusz.kubalewski@intel.com \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=grzegorz.nitka@intel.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=maciej.machnikowski@intel.com \
--cc=netdev-bot+sashiko@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pmenzel@molgen.mpg.de \
--cc=poros@redhat.com \
--cc=przemyslaw.korba@intel.com \
--cc=richardcochran@gmail.com \
--cc=sergey.temerkhanov@intel.com \
/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