From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BCE2B48592E for ; Tue, 22 Sep 2026 18:08:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.8 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790100524; cv=none; b=ciTDA2UbKGpYdw209oe0L3Aef1P8/tciA1sNvn+8MOr2jVlobzMU8mj23H8QOKW02fQv0Dhmc4/r9IdVoovSGhZ3KH3xhIL0ludZv3klrfGJ/Qq3cm5ehIQtHerro5ZCaBbrgakzrBXHIYplbXb8Hb49WURerksS2QLHIu2W7RI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790100524; c=relaxed/simple; bh=o6q8akGBg1N3Y/iOLxvXvs3dNA4GaThrYun7KxJYPhs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=d+tDu4VNrSJoI7DWyuS1PzzHU3ELwwzoZGIVnrHN5j71ACZyzHBCdkv1F1S6YGGRkrhusTFnEt4AaZzNA4umWQg51OAS68Hth+HO+D2Uv9kSwcxtt7j3gwxGyWBbtg66qqMG8yow7Kgq/FTi0bdKqvrSM14p6TqCzZvvEemvLzY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=hUCJqEbW; arc=none smtp.client-ip=192.198.163.8 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="hUCJqEbW" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1790100518; x=1821636518; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=o6q8akGBg1N3Y/iOLxvXvs3dNA4GaThrYun7KxJYPhs=; b=hUCJqEbWrkUWKPVWc5OpSrDCoY7plilXc6C4KxxKEY9pgzAqM22rTkBw 7F2vOYecMPDOcICVAd8i4s6/X3HEyZu3KWesUT7QH0mbk0MP4Eb0Iq15F bT83pKxvP9l5NXuhMQUV54l9I4DNuDFw398OAbbeB1O4yoYFMg87D9U+I t2Hv0PFd8PBAkv0TvUxDEdQt+3jJovNLdxQ+ugpYH0mcmdlUdifMOgfyc sw9lcMW2XV1agDDP+hW+TvhC0Wf2ZW9G9YYJqjtIvkO10FCb6ECkHDVzE WCwk5+QzOy0+GSwVV41ZlWuEyrwHUaZEZF9SgKLI4BCX/7vwzmcjuz+SL g==; X-CSE-ConnectionGUID: VXu3CU1AQq2sLpxChdE41A== X-CSE-MsgGUID: JcALOPQ3SLaIRCp0t1GpYw== X-IronPort-AV: E=McAfee;i="6800,10657,11913"; a="108232054" X-IronPort-AV: E=Sophos;i="6.27,116,1787036400"; d="scan'208";a="108232054" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Sep 2026 11:04:24 -0700 X-CSE-ConnectionGUID: xAxmdzKSTUWhKoi9Jyy2zw== X-CSE-MsgGUID: JVbhBlNOTK+ScH+UTqR5EQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,116,1787036400"; d="scan'208";a="281315341" Received: from orcnseosdtjek.jf.intel.com (HELO [10.166.28.109]) ([10.166.28.109]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Sep 2026 11:04:24 -0700 From: Jacob Keller Date: Tue, 22 Sep 2026 11:02:45 -0700 Subject: [PATCH iwl-net v2 12/15] ice: keep Tx timestamp slots tracked until completion or timeout Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260922-jk-e825c-timestamp-processing-logic-fixes-srcu-v2-12-e55b692d0e6b@intel.com> References: <20260922-jk-e825c-timestamp-processing-logic-fixes-srcu-v2-0-e55b692d0e6b@intel.com> In-Reply-To: <20260922-jk-e825c-timestamp-processing-logic-fixes-srcu-v2-0-e55b692d0e6b@intel.com> To: Jacob Keller , Grzegorz Nitka , Arkadiusz Kubalewski , Intel Wired LAN , Maciej Machnikowski , Przemyslaw Korba , netdev@vger.kernel.org, Anthony Nguyen Cc: Jacob Keller , Petr Oros , Maciek Machnikowski X-Mailer: b4 0.17-dev-8b7ea X-Developer-Signature: v=1; a=openpgp-sha256; l=9215; i=jacob.e.keller@intel.com; h=from:subject:message-id; bh=bScmJ2APos81Wpd63uPUzOiy9ePSLtU37ePBl7tRMiQ=; b=owGbwMvMwCWWNS3WLp9f4wXjabUkhqxNh2Us8jUKXt8+9rXvX33+1a6rHakbmWUCZ9xRO6VY8 c7iQ+W1jlIWBjEuBlkxRRYFh5CV140nhGm9cZaDmcPKBDKEgYtTACbib8Pwv+pdJ0dVyU4j59lZ Whse/Dn7ZvZ+3e4JP7oSkwJCrhlMt2D4Z7LlfmRhhGPQt4usBW1ttSdmXlHx3Lj42Xw/Z5Xr9ce e8QEA X-Developer-Key: i=jacob.e.keller@intel.com; a=openpgp; fpr=204054A9D73390562AEC431E6A965D3E6F0F28E8 From: Petr Oros When the link goes down the processing loop drops every outstanding request, and a request whose timestamp is not ready yet is freed without reading the PHY slot. The hardware completes the capture a moment later, the orphaned ready bit blocks the port interrupt until the next link-up sweep, and the freed index can meanwhile be reused by a new request whose slot the hardware then overwrites. Captured on a reproducer as ready bits with no in_use owner right after a link bounce. Stop dropping on link down. Mark the outstanding requests stale so their completions are read and discarded, reject new requests while the link is down, and free a not yet ready slot only after the two second timeout. This way an index is never reused while the hardware can still write it and never left untracked while a completion can still arrive. To avoid an IRQ storm in the event that we really do have a stale packet that is not timestamped, modify ice_ptp_tx_tstamps_pending() to ignore stale timestamps when checking for whether to re-arm the IRQ from the miscellaneous thread function. Instead, only check for stale packets in the auxiliary work thread. This way we do not check in a tight loop waiting for a timestamp that may never come. To ensure that forward progress is made on clearing stale timestamps, fix the check for ice_ptp_maybe_trigger_tx_interrupt to properly apply for devices that manage their own interrupt, instead of only checking on the clock owner. This effectively reverts commit fcc2cef37fed ("ice/ptp: fix the PTP worker retrying indefinitely if the link went down"), which tried to release an index before this 2 second wait period. Fixes: fcc2cef37fed ("ice/ptp: fix the PTP worker retrying indefinitely if the link went down") Suggested-by: Jacob Keller Signed-off-by: Petr Oros Reviewed-by: Maciek Machnikowski Signed-off-by: Jacob Keller --- drivers/net/ethernet/intel/ice/ice_ptp.h | 8 +++-- drivers/net/ethernet/intel/ice/ice_main.c | 2 +- drivers/net/ethernet/intel/ice/ice_ptp.c | 51 ++++++++++++++++--------------- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h index 029ee4612d76..7810fefc546e 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp.h @@ -132,6 +132,9 @@ struct ice_ptp_tx { #define INDEX_PER_PORT_E82X 16 #define INDEX_PER_PORT 64 +/* Maximum number of timestamp indexes across all devices */ +#define INDEX_PER_PORT_MAX INDEX_PER_PORT + /** * struct ice_ptp_port - data used to initialize an external port for PTP * @@ -314,7 +317,7 @@ void ice_ptp_req_tx_single_tstamp(struct ice_ptp_tx *tx, u8 idx); void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx); void ice_ptp_process_ts(struct ice_pf *pf); irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf); -bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf); +bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf, bool in_irq); u64 ice_ptp_read_src_clk_reg(struct ice_pf *pf, struct ptp_system_timestamp *sts); @@ -362,7 +365,8 @@ static inline irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf) return IRQ_HANDLED; } -static inline bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf) +static inline bool +ice_ptp_tx_tstamps_pending(struct ice_pf *pf, bool in_irq) { return false; } diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index f32041dd8b27..d12952171a99 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3248,7 +3248,7 @@ static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data) ice_irq_dynamic_ena(hw, NULL, NULL); ice_flush(hw); - if (ice_ptp_tx_tstamps_pending(pf)) { + if (ice_ptp_tx_tstamps_pending(pf, true)) { /* If any new Tx timestamps happened while in interrupt, * re-arm the interrupt to trigger it again. */ diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c index 142d9e1c1f2e..06f383415d07 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c @@ -365,9 +365,12 @@ static u64 ice_ptp_extend_40b_ts(struct ice_pf *pf, u64 in_tstamp) static bool ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx) { + struct ice_ptp_port *ptp_port = + container_of(tx, struct ice_ptp_port, tx); + lockdep_assert_held(&tx->lock); - return tx->init && !tx->calibrating; + return tx->init && !tx->calibrating && READ_ONCE(ptp_port->link_up); } /** @@ -564,7 +567,6 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) struct ice_pf *pf; struct ice_hw *hw; u64 tstamp_ready; - bool link_up; int err; u8 idx; @@ -582,14 +584,11 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) return; } - /* Drop packets if the link went down */ - link_up = READ_ONCE(ptp_port->link_up); - for_each_set_bit(idx, tx->in_use, tx->len) { struct skb_shared_hwtstamps shhwtstamps = {}; u8 phy_idx = idx + tx->offset; u64 raw_tstamp = 0, tstamp; - bool drop_ts = !link_up; + bool drop_ts = false; struct sk_buff *skb; /* Prevent speculative re-ordering of start and skb */ @@ -1399,6 +1398,10 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup) if (pf->hw.reset_ongoing) { mutex_lock(&pf->adapter->ps_lock); WRITE_ONCE(ptp_port->link_up, linkup); + + if (!linkup) + ice_ptp_mark_tx_tracker_stale(&ptp_port->tx); + mutex_unlock(&pf->adapter->ps_lock); return; } @@ -1448,6 +1451,9 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup) */ WRITE_ONCE(ptp_port->link_up, linkup); + if (!linkup) + ice_ptp_mark_tx_tracker_stale(&ptp_port->tx); + switch (hw->mac_type) { case ICE_MAC_E810: case ICE_MAC_E830: @@ -2804,21 +2810,22 @@ void ice_ptp_process_ts(struct ice_pf *pf) } } -static bool ice_port_has_timestamps(struct ice_ptp_tx *tx) +static bool ice_port_has_timestamps(struct ice_ptp_tx *tx, bool in_irq) { - bool more_timestamps; + DECLARE_BITMAP(tstamps, INDEX_PER_PORT_MAX) = {}; scoped_guard(spinlock_irqsave, &tx->lock) { if (!tx->init) return false; - more_timestamps = !bitmap_empty(tx->in_use, tx->len); + if (in_irq) + return bitmap_andnot(tstamps, tx->in_use, tx->stale, tx->len); + else + return !bitmap_empty(tx->in_use, tx->len); } - - return more_timestamps; } -static bool ice_any_port_has_timestamps(struct ice_pf *pf) +static bool ice_any_port_has_timestamps(struct ice_pf *pf, bool in_irq) { struct ice_port_list *ports = &pf->adapter->ports; bool have_tstamps = false; @@ -2832,7 +2839,7 @@ static bool ice_any_port_has_timestamps(struct ice_pf *pf) if (!kref_get_unless_zero(&port->ref)) continue; - if (ice_port_has_timestamps(&port->tx)) + if (ice_port_has_timestamps(&port->tx, in_irq)) have_tstamps = true; kref_put(&port->ref, ice_ptp_release_port_srcu); @@ -2846,7 +2853,7 @@ static bool ice_any_port_has_timestamps(struct ice_pf *pf) return have_tstamps; } -bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf) +bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf, bool in_irq) { struct ice_hw *hw = &pf->hw; int ret; @@ -2856,11 +2863,11 @@ bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf) case ICE_PTP_TX_INTERRUPT_NONE: return false; case ICE_PTP_TX_INTERRUPT_SELF: - if (ice_port_has_timestamps(&pf->ptp.port.tx)) + if (ice_port_has_timestamps(&pf->ptp.port.tx, in_irq)) return true; break; case ICE_PTP_TX_INTERRUPT_ALL: - if (ice_any_port_has_timestamps(pf)) + if (ice_any_port_has_timestamps(pf, in_irq)) return true; break; default: @@ -2936,7 +2943,7 @@ irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf) /* E830 can read timestamps in the top half using rd32() */ ice_ptp_process_ts(pf); - if (ice_ptp_tx_tstamps_pending(pf)) { + if (ice_ptp_tx_tstamps_pending(pf, true)) { /* Process outstanding Tx timestamps. If there * is more work, re-arm the interrupt to trigger again. */ @@ -2966,19 +2973,15 @@ static void ice_ptp_maybe_trigger_tx_interrupt(struct ice_pf *pf) { struct device *dev = ice_pf_to_dev(pf); struct ice_hw *hw = &pf->hw; - int ret; if (!pf->ptp.port.tx.has_ready_bitmap) return; - if (!ice_pf_src_tmr_owned(pf)) + if (pf->ptp.tx_interrupt_mode != ICE_PTP_TX_INTERRUPT_SELF && + !ice_pf_src_tmr_owned(pf)) return; - ret = ice_check_phy_tx_tstamp_ready(hw); - if (ret < 0) { - dev_dbg(dev, "PTP periodic task unable to read PHY timestamp ready bitmap, err %d\n", - ret); - } else if (ret) { + if (ice_ptp_tx_tstamps_pending(pf, false)) { dev_dbg(dev, "PTP periodic task detected waiting timestamps. Triggering Tx timestamp interrupt now.\n"); wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M); -- 2.56.0.rc0.395.gd1f3524e15dc