From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.14]) (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 6F28530D407 for ; Fri, 11 Sep 2026 00:34:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.14 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789086894; cv=none; b=t8mnuQSO3KM/f6WOiRe/sxo1YWy8mC7zFJnmtIrLit7RgBYwMCHdpPtdVBSUZSyj4IdTE3tG7AtmgRmAO1ExXMCBQmGS/q4ubvztImB2ar7TTrnDJs33Zop/L8EWtR8UMMW1tUW8CZGYZtXt40yzbtKZoo36BSTEdKGeQf5u5eI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789086894; c=relaxed/simple; bh=g2xuJ3XjVa/v0qTIasFaxxF6s6EFg/82rngxEbG6SXo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZhbRp5T2UrOmYHYuQ1ulsVxhW74Q/Jdw3r2PysozaqMU6ieBrrCP4QFRY7Drl+ZbGZaw2RLwQapBqP1rK78uMJbJ70gSRKgrjlrTZXaCi3MzbXlZ8b7mfD49Sqb4s6vZEo/0CO7RKPGRu2bi9s4IYlnLoUX9BZWoXu83EuthDA8= 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=aKVxkJWB; arc=none smtp.client-ip=192.198.163.14 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="aKVxkJWB" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1789086892; x=1820622892; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=g2xuJ3XjVa/v0qTIasFaxxF6s6EFg/82rngxEbG6SXo=; b=aKVxkJWBcdsJgkYkVm3b9yLa0N/+F0YQH6OeCTWjFryDioGjBOtN3Ylx SOWYMOBpc4+qGAHFqnpx/r+aBOjNj0klEBHkEjsaairjVVM/wnUns0nMr 4cDoY73BrTcZ0Kev7iolMFGs+0cmob8FfErVnQCFlJhHlRceHzagQsgIT ZvhuHeo/jZqRZsDrIwyQoRu3UUATZ7roeEyvwmarD75yq2dllC/a6nwcA FrJ9p4175Z/xJTJejm+MQTtSzz6QBVwYQliFDSSHSp1PqfQ5ZsuSS1rhV 6k+L4o5Enw2xxkI3eJyPSNGyWidDquC3LuQ4EI6b0Wjp0AYseSDqp/HTZ Q==; X-CSE-ConnectionGUID: uQvOa1tdRkGyN7AK9AiVvQ== X-CSE-MsgGUID: U7WVBKD1RWeIT1V9C+5fLA== X-IronPort-AV: E=McAfee;i="6800,10657,11901"; a="89564742" X-IronPort-AV: E=Sophos;i="6.27,96,1787036400"; d="scan'208";a="89564742" Received: from orviesa009.jf.intel.com ([10.64.159.149]) by fmvoesa108.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Sep 2026 17:34:44 -0700 X-CSE-ConnectionGUID: YMjALYT7Qhaz8UJedt5bQA== X-CSE-MsgGUID: PZs5DFw4TGOc8cFMM7wwxg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,96,1787036400"; d="scan'208";a="272291087" Received: from anguy11-upstream.jf.intel.com ([10.166.9.133]) by orviesa009.jf.intel.com with ESMTP; 10 Sep 2026 17:34:45 -0700 From: Tony Nguyen To: davem@davemloft.net, kuba@kernel.org, pabeni@redhat.com, edumazet@google.com, andrew+netdev@lunn.ch, netdev@vger.kernel.org Cc: Petr Oros , anthony.l.nguyen@intel.com, jacob.e.keller@intel.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, Alexander Nowlin Subject: [PATCH net 11/15] ice: keep Tx timestamp slots tracked until completion or timeout Date: Thu, 10 Sep 2026 17:34:20 -0700 Message-ID: <20260911003430.3386340-12-anthony.l.nguyen@intel.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20260911003430.3386340-1-anthony.l.nguyen@intel.com> References: <20260911003430.3386340-1-anthony.l.nguyen@intel.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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. 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 Signed-off-by: Jacob Keller Reviewed-by: Maciek Machnikowski Tested-by: Alexander Nowlin Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_main.c | 2 +- drivers/net/ethernet/intel/ice/ice_ptp.c | 44 +++++++++++------------ drivers/net/ethernet/intel/ice/ice_ptp.h | 8 +++-- 3 files changed, 28 insertions(+), 26 deletions(-) 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 b142b779dc10..299de9d49423 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c @@ -364,9 +364,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 && ptp_port->link_up; } /** @@ -563,7 +566,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; @@ -581,14 +583,11 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) return; } - /* Drop packets if the link went down */ - link_up = 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; /* Drop packets which have waited for more than 2 seconds */ @@ -1371,6 +1370,9 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup) if (pf->hw.reset_ongoing) goto exit_kref_put; + if (!linkup) + ice_ptp_mark_tx_tracker_stale(&ptp_port->tx); + if (hw->mac_type == ICE_MAC_GENERIC_3K_E825 && test_bit(ICE_FLAG_DPLL, pf->flags)) { int pin, err; @@ -2767,28 +2769,29 @@ 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) { bool have_tstamps = false; struct ice_ptp_port *port; rcu_read_lock(); list_for_each_entry_rcu(port, &pf->adapter->ports.list, list_node) { - if (ice_port_has_timestamps(&port->tx)) { + if (ice_port_has_timestamps(&port->tx, in_irq)) { have_tstamps = true; break; } @@ -2798,7 +2801,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; @@ -2808,11 +2811,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: @@ -2888,7 +2891,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. */ @@ -2918,7 +2921,6 @@ 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; @@ -2926,11 +2928,7 @@ static void ice_ptp_maybe_trigger_tx_interrupt(struct ice_pf *pf) if (!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); diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h index da2003ba3bb0..13158a9319fb 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 * @@ -316,7 +319,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); @@ -364,7 +367,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; } -- 2.47.1