Netdev List
 help / color / mirror / Atom feed
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>, <poros@redhat.com>,
	<maciej.machnikowski@intel.com>, <przemyslaw.korba@intel.com>,
	<grzegorz.nitka@intel.com>, <sergey.temerkhanov@intel.com>,
	<arkadiusz.kubalewski@intel.com>, <richardcochran@gmail.com>,
	<horms@kernel.org>
Subject: Re: [PATCH net v3 14/14] ice: don't clear in_use until HW clears ready bitmap
Date: Mon, 19 Oct 2026 17:18:02 -0700	[thread overview]
Message-ID: <388b2dd4-13ee-4377-8d99-39f56a77762c@intel.com> (raw)
In-Reply-To: <179244085807.3135.9409141978116916415@kernel.org>

On 10/19/2026 1:14 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: 0 · Medium: 3 · Low: 1
> 
> 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).
> 
> - [Medium] In ice_ptp_maybe_trigger_tx_interrupt()
>   (drivers/net/ethernet/intel/ice/ice_ptp.c), the patch now reads the…
> - [Medium] ice_ptp_flush_tx_tracker() now increments
>   pf->ptp.tx_hwtstamp_flushed on every flushed request, and also…
> - [Medium] The new 'ready bit not cleared' branch in
>   ice_ptp_process_tx_tstamp() decides based on PHY reads done without…
> - [Low] pf->ptp.tx_hwtstamp_timeouts now has two writers that are not
>   serialized against each other.
> 
> --
> 
> ice: don't clear in_use until HW clears ready bitmap
> 
> This commit re-reads the PHY Tx timestamp ready bitmap after each read in
> ice_ptp_process_tx_tstamp(). If the hardware did not clear the bit, the
> index stays locked and is marked stale. It also moves the timeout count to
> the point where the index is released, counts timeouts on flush, and moves
> the hardware ready bitmap check out of ice_ptp_tx_tstamps_pending() and
> into ice_ptp_maybe_trigger_tx_interrupt().
> 
>> diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
>> index a9658f859c2e8..74e0c0138c501 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_ptp.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
> 
> [ ... ]
> 
>> @@ -627,6 +622,27 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx)
>>  		if (err && !drop_ts)
>>  			continue;
>>  
>> +		/* verify ready bit cleared */
>> +		if (tx->has_ready_bitmap) {
>> +			err = ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready);
>> +			if (err || tstamp_ready & BIT_ULL(phy_idx)) {
>> +				spin_lock_irqsave(&tx->lock, flags);
>> +				if (test_bit(idx, tx->in_use) &&
>> +				    !test_and_set_bit(idx, tx->stale))
>> +					dev_dbg(ice_pf_to_dev(pf), "PHY port %u failed to clear ready bit for idx %u\n",
>> +						ptp_port->port_num, phy_idx);
>> +				skb = tx->tstamps[idx].skb;
>> +				tx->tstamps[idx].skb = NULL;
>> +				spin_unlock_irqrestore(&tx->lock, flags);
>> +				/* Free the SKB immediately since we're never
>> +				 * going to report a timestamp for the stale
>> +				 * packet.
>> +				 */
>> +				dev_kfree_skb_any(skb);
>> +				continue;
>> +			}
>> +		}
> 
> [Severity: Medium]
> Can this branch mark a newer request in the same slot as stale and free
> its skb?
> 
> The decision here comes from ice_read_phy_tstamp() and the ready bitmap
> re-read. Neither is done under tx->lock. After the lock is taken, the only
> check is test_bit(idx, tx->in_use), and that check can't tell the original
> request from a new one that reused idx.
> 
> On E825, a link-up event can run this sequence while the IRQ thread sits
> between the re-read and spin_lock_irqsave():
> 
> ice_ptp_link_change()
>   ice_ptp_port_phy_restart()
>     ptp_port->tx.calibrating = true;
>     ice_ptp_flush_tx_tracker()   /* clears in_use[idx], frees skb */
>     ice_start_phy_timer_eth56g()
>     ptp_port->tx.calibrating = false;
> 
> ice_ptp_request_ts()
>     tx->tstamps[idx].start = jiffies;
>     tx->tstamps[idx].skb = skb_get(skb);
>     ...
>     clear_bit(idx, tx->stale);
>     smp_mb__before_atomic();
>     set_bit(idx, tx->in_use);
> 
> Nothing in that sequence waits for an IRQ thread that is already inside the
> loop. When the IRQ thread resumes, test_bit(idx, tx->in_use) returns true.
> It then sets stale[idx] and frees the new request's skb because of the old
> request's hardware state. The new packet's Tx timestamp is lost and
> skb_tstamp_tx() is never called for it.
> 
> The timing window is narrow, and the freed reference came from skb_get(),
> so this is a lost timestamp, not a memory safety issue. The existing
> skip_ts_read path has a similar check-then-act gap.
> 

Of course. The change to flush tracker was problematic afterall.
Reverting back to marking stale should fix it.

>>  		ice_trace(tx_tstamp_fw_done, tx->tstamps[idx].skb, idx);
>>  
>>  		/* For PHYs which don't implement a proper timestamp ready
>> @@ -643,6 +659,9 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx)
>>  			drop_ts = true;
>>  
>>  skip_ts_read:
>> +		if (timeout)
>> +			pf->ptp.tx_hwtstamp_timeouts++;
>> +
>>  		spin_lock_irqsave(&tx->lock, flags);
>>  		if (!tx->has_ready_bitmap && raw_tstamp)
>>  			tx->tstamps[idx].cached_tstamp = raw_tstamp;
> 
> [Severity: Low]
> Is the timeout counted here only when this path is the one that actually
> releases the index?
> 
> The increment happens before tx->lock is taken, and it doesn't check that
> in_use[idx] is still set. This patch also adds an increment of
> tx_hwtstamp_timeouts in ice_ptp_flush_tx_tracker(), under tx->lock.
> 
> On E82x/E825, ice_ptp_process_tx_tstamp() runs in the clock owner's misc
> IRQ thread without ps_lock. The flush can run at the same time from
> ice_ptp_port_phy_restart() (E825 link up), from
> ice_ptp_flush_all_tx_tracker() during reset, or from tracker release.
> 
> Here is one way it can happen:
> 
> 1. The IRQ thread sees a request that is older than 2 seconds with its
>    ready bit clear, sets timeout = true and jumps to skip_ts_read.
> 2. The flush takes tx->lock, increments tx_hwtstamp_timeouts and clears
>    in_use.
> 3. The IRQ thread increments tx_hwtstamp_timeouts again, and its
>    clear_bit() does nothing.
> 
> One request ends up counted twice. Also, a plain u32 increment from two
> CPUs can lose updates.
> 
> The commit message says:
> 
>   "This ensures that we don't double count timeouts or count them
>   prematurely."
> 
> Is that still true now that the flush path also increments this counter?
> 

I'm going to revert that flush change back which should address this.

> [ ... ]
> 
>> @@ -849,14 +869,20 @@ ice_ptp_flush_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx)
>>  			ice_clear_phy_tstamp(hw, tx->block, phy_idx);
>>  
>>  		spin_lock_irqsave(&tx->lock, flags);
>> +
>> +		/* Count the number of Tx timestamps flushed */
>> +		pf->ptp.tx_hwtstamp_flushed++;
>> +
>> +		/* Also count timeouts if we flush a request that timed out */
>> +		if (time_is_before_jiffies(tx->tstamps[idx].start + 2 * HZ))
>> +			pf->ptp.tx_hwtstamp_timeouts++;
>> +
> 
> [Severity: Medium]
> Doesn't this count one flushed request as both err and lost in the ethtool
> timestamping stats?
> 
> Both counters are incremented here for the same idx. ice_get_ts_stats()
> reports them as:
> 
> drivers/net/ethernet/intel/ice/ice_ethtool.c:ice_get_ts_stats() {
>     ...
> 	ts_stats->err = ptp->tx_hwtstamp_skipped +
> 			ptp->tx_hwtstamp_flushed +
> 			ptp->tx_hwtstamp_discarded;
> 	ts_stats->lost = ptp->tx_hwtstamp_timeouts;
> }
> 
> The kernel-doc for struct ethtool_ts_stats in include/linux/ethtool.h says:
> 
>  * @err: Number of arbitrary timestamp generation error events that the
>  *	hardware encountered, exclusive of @lost statistics.
> 
> This patch lets stuck slots stay locked for well over 2 seconds, so the
> E825 link-up flush from ice_ptp_port_phy_restart() is likely to hit this
> case. Should tx_hwtstamp_flushed be skipped when the request is counted as
> a timeout?
> 
> A related detail: an index whose skb was already freed by the new
> stuck-ready-bit path still counts towards tx_hwtstamp_flushed, even though
> tx->tstamps[idx].skb is NULL. Is that intended?
> 
> [ ... ]
> 
>> @@ -3001,7 +3009,15 @@ static void ice_ptp_maybe_trigger_tx_interrupt(struct ice_pf *pf)
>>  	    !ice_pf_src_tmr_owned(pf))
>>  		return;
>>  
>> -	if (ice_ptp_tx_tstamps_pending(pf, false)) {
>> +	ret = ice_check_phy_tx_tstamp_ready(hw);
>> +	if (ret < 0) {
>> +		dev_dbg(dev, "Unable to read PHY Tx timestamp ready bitmap, err %pe\n",
>> +			ERR_PTR(ret));
>> +		/* Don't trigger an IRQ if we are unable to access the PHY */
>> +		return;
>> +	}
>> +
>> +	if (ret > 0 || ice_ptp_tx_tstamps_pending(pf, false)) {
> 
> [Severity: Medium]
> Can this early return stop the watchdog from re-triggering the interrupt
> for ports that still have outstanding requests?
> 
> Before this patch, ice_ptp_tx_tstamps_pending(pf, false) checked the
> software in_use bitmaps first, and returned true whenever any request was
> outstanding. The hardware check only ran when software had nothing
> pending, and an error from it only turned off that hardware-only trigger.
> 
> Now the hardware read happens first. On E82x and E825
> (ICE_PTP_TX_INTERRUPT_ALL on the clock owner), ice_check_phy_tx_tstamp_ready()
> walks every quad or port and returns the first error it hits:
> 
> drivers/net/ethernet/intel/ice/ice_ptp_hw.c:ice_check_phy_tx_tstamp_ready_eth56g() {
> 	for (port = 0; port < hw->ptp.num_lports; port++) {
> 		...
> 		err = ice_get_phy_tx_tstamp_ready(hw, port, &tstamp_ready);
> 		if (err)
> 			return err;
>     ...
> }
> 
> ice_check_phy_tx_tstamp_ready_e82x() does the same across quads.
> 
> As long as one PHY can't be read, the watchdog triggers no IRQ for any
> port. ice_ptp_process_tx_tstamp() is not re-run, so timed-out or stale
> slots on healthy ports are not reaped and a stalled hardware interrupt is
> not recovered.
> 
> This patch also stops the IRQ path from re-arming for stale entries and
> for link-down or calibrating trackers, which leaves the watchdog as the
> only fallback. The commit message also says PHY access errors can happen
> during the link transition window this patch targets. The commit message
> doesn't mention this ordering change.
> 
> The kernel-doc for ice_ptp_maybe_trigger_tx_interrupt() still says:
> 
>  * To avoid getting permanently stuck, periodically check if there is any
>  * outstanding timestamps or if the PHY has marked any index as ready.
> 
> Would it work to check ice_ptp_tx_tstamps_pending() first, and treat a
> hardware read error the same as no hardware-ready timestamps?
> 
>>  		dev_dbg(dev, "PTP periodic task detected waiting timestamps. Triggering Tx timestamp interrupt now.\n");
>>  
>>  		wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M);
> 

I can try to order this better. In practice the thought I had was that
if we can't access the PHY anyways we shouldn't really be triggering an
IRQ since the only known paths for a failure to acecss PHY are because
the sideband queue is blocked which we don't really expect to be a
transient failure. However in principle there is nothing that guarantees
that...  Fine.


      reply	other threads:[~2026-10-20  0:18 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-15 19:10 [PATCH net v3 00/14][pull request] ice: E82x: timestamp processing logic fixes Tony Nguyen
2026-10-15 19:10 ` [PATCH net v3 01/14] ice: fix removal of PTP timestamp tracker during reset Tony Nguyen
2026-10-19 20:14   ` netdev-bot+sashiko
2026-10-19 23:14     ` Jacob Keller
2026-10-15 19:10 ` [PATCH net v3 02/14] ice: use reference counting and SRCU for PTP port access Tony Nguyen
2026-10-19 20:14   ` netdev-bot+sashiko
2026-10-19 23:16     ` Jacob Keller
2026-10-15 19:10 ` [PATCH net v3 03/14] ice: fix PHY port restart serialization Tony Nguyen
2026-10-19 20:14   ` netdev-bot+sashiko
2026-10-19 23:21     ` Jacob Keller
2026-10-15 19:10 ` [PATCH net v3 04/14] ice: set in_use only after preparing Tx timestamp index Tony Nguyen
2026-10-15 19:10 ` [PATCH net v3 05/14] ice: call PTP link change only from link events Tony Nguyen
2026-10-19 20:14   ` netdev-bot+sashiko
2026-10-19 23:35     ` Jacob Keller
2026-10-15 19:10 ` [PATCH net v3 06/14] ice: E822: keep Tx timestamps disabled during offset calibration Tony Nguyen
2026-10-19 20:14   ` netdev-bot+sashiko
2026-10-19 23:37     ` Jacob Keller
2026-10-15 19:10 ` [PATCH net v3 07/14] ice: E822: cancel offset verification work during reset preparation Tony Nguyen
2026-10-19 20:14   ` netdev-bot+sashiko
2026-10-19 23:40     ` Jacob Keller
2026-10-15 19:10 ` [PATCH net v3 08/14] ice: E825: stop clearing PHY_REG_TX_OFFSET_READY Tony Nguyen
2026-10-19 20:14   ` netdev-bot+sashiko
2026-10-19 23:42     ` Jacob Keller
2026-10-20  1:53       ` Jacob Keller
2026-10-15 19:10 ` [PATCH net v3 09/14] ice: E825: clear PHY_TSTAMP memory prior to soft reset Tony Nguyen
2026-10-19 20:14   ` netdev-bot+sashiko
2026-10-19 23:49     ` Jacob Keller
2026-10-15 19:10 ` [PATCH net v3 10/14] ice: E825: perform a soft reset when starting the PHY timer Tony Nguyen
2026-10-19 20:14   ` netdev-bot+sashiko
2026-10-19 23:57     ` Jacob Keller
2026-10-15 19:10 ` [PATCH net v3 11/14] ice: wait for in-flight Tx timestamps before removing the tracker Tony Nguyen
2026-10-19 20:14   ` netdev-bot+sashiko
2026-10-20  0:05     ` Jacob Keller
2026-10-15 19:10 ` [PATCH net v3 12/14] ice: keep Tx timestamp slots tracked until completion or timeout Tony Nguyen
2026-10-19 20:14   ` netdev-bot+sashiko
2026-10-20  0:11     ` Jacob Keller
2026-10-15 19:10 ` [PATCH net v3 13/14] ice: skip reading Tx ready bitmap on ports with no timestamps Tony Nguyen
2026-10-15 19:11 ` [PATCH net v3 14/14] ice: don't clear in_use until HW clears ready bitmap Tony Nguyen
2026-10-19 20:14   ` netdev-bot+sashiko
2026-10-20  0:18     ` Jacob Keller [this message]

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=388b2dd4-13ee-4377-8d99-39f56a77762c@intel.com \
    --to=jacob.e.keller@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=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