From nobody Sun Feb 8 03:57:30 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (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 C77A73C1F; Thu, 27 Nov 2025 06:09:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764223758; cv=none; b=mMUAxfl6u7YBq+4EuopSO/YJXCVC39gI+fye89SDjFgu+hn8u/jXUVBT6Ru49VohFha/ZHFTz7NCLmdW6OBv63I1K8IUC3kY5TOjv0v92EdXEsS6QLpoOE5DKDFA3I9Aq0osGIW/fUDWImj9C97Hv0b03rR4A16N0Bnve1egX6U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764223758; c=relaxed/simple; bh=aHUC8nU4inAMF0lcxnfBXRfDJnB0i8imv9buU6Z9arU=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; b=oYmWj+ESk38QR4oEwdemhDjjkSxbzzNqX4O5xjmoGIScfbUGEkDhOmqe8F60qiuw58xxGW4ZMuWDqo2Es6+W5KL2rmnM60qtOrMeR3pshB7Burk+5FiNn48h2iVy07N8IdSugKSuivGsJgDd4ovJSNThjWV7AhKuYetAp25B11U= 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=FF2+OwUF; arc=none smtp.client-ip=198.175.65.19 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="FF2+OwUF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1764223755; x=1795759755; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=aHUC8nU4inAMF0lcxnfBXRfDJnB0i8imv9buU6Z9arU=; b=FF2+OwUFOESEXZNx2Jn7B8qy7YUx2pw5w2ybC1rWbrqwnwDU9Ykj0o3i LjLm68eAanGhGWi/rV+oBPfDXkk5JRxxOHl7snewZZzS2+Ga9A1jGj69u lRLM2ew9YwZc1W6pZYMVTjOj4i1yYWxlqnvsSQA+/GladxYxHLgnAjJy5 /7ZQj+6TeRgjtJuJHFuMUnEncBWW9SLRu7Yyv7SNn9RKd/UD9vDEDko4J MGd12ZuSuHh7pQ6DZai1oQqMvTueNd1TsQYrgCNjEqTVOlrFYub3BNvPX tiiunHOFvsIMyGSIQ7zoAV7uQ2NzQk+N6IBh1P1q4KoNPpN2Y1jDSq1sp A==; X-CSE-ConnectionGUID: icfDowFGQHOErcKHZwOayQ== X-CSE-MsgGUID: buc4KkmwSYei0ycXhGPl0Q== X-IronPort-AV: E=McAfee;i="6800,10657,11625"; a="66152496" X-IronPort-AV: E=Sophos;i="6.20,230,1758610800"; d="scan'208";a="66152496" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Nov 2025 22:09:14 -0800 X-CSE-ConnectionGUID: EVF9C2O+SjiFGmSG7wL5Cw== X-CSE-MsgGUID: vE3Dx5+ZRZOttXv2lq5bAw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.20,230,1758610800"; d="scan'208";a="193956120" Received: from p2dy149cchoong.png.intel.com ([10.107.243.50]) by fmviesa010.fm.intel.com with ESMTP; 26 Nov 2025 22:09:12 -0800 From: Chwee-Lin Choong To: Tony Nguyen , Przemek Kitszel , Andrew Lunn , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Richard Cochran , Vinicius Costa Gomes Cc: intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Avi Shalev , Song Yoong Siang , Chwee-Lin Choong Subject: [PATCH iwl-net v2] igc: fix race condition in TX timestamp read for register 0 Date: Thu, 27 Nov 2025 21:49:27 +0800 Message-ID: <20251127134927.2133-1-chwee.lin.choong@intel.com> X-Mailer: git-send-email 2.42.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The current HW bug workaround checks the TXTT_0 ready bit first, then reads TXSTMPL_0 twice (before and after reading TXSTMPH_0) to detect whether a new timestamp was captured by timestamp register 0 during the workaround. This sequence has a race: if a new timestamp is captured after checking the TXTT_0 bit but before the first TXSTMPL_0 read, the detection fails because both the =E2=80=9Cold=E2=80=9D and =E2=80=9Cnew=E2= =80=9D values come from the same timestamp. Fix by reading TXSTMPL_0 first to establish a baseline, then checking the TXTT_0 bit. This ensures any timestamp captured during the race window will be detected. Old sequence: 1. Check TXTT_0 ready bit 2. Read TXSTMPL_0 (baseline) 3. Read TXSTMPH_0 (interrupt workaround) 4. Read TXSTMPL_0 (detect changes vs baseline) New sequence: 1. Read TXSTMPL_0 (baseline) 2. Check TXTT_0 ready bit 3. Read TXSTMPH_0 (interrupt workaround) 4. Read TXSTMPL_0 (detect changes vs baseline) Fixes: c789ad7cbebc ("igc: Work around HW bug causing missing timestamps") Suggested-by: Avi Shalev Signed-off-by: Song Yoong Siang Signed-off-by: Chwee-Lin Choong Reviewed-by: Aleksandr Loktionov --- v2: Added detailed comments explaining the hardware bug workaround and race detection mechanism --- drivers/net/ethernet/intel/igc/igc_ptp.c | 43 ++++++++++++++---------- export | 0 2 files changed, 25 insertions(+), 18 deletions(-) create mode 100644 export diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/etherne= t/intel/igc/igc_ptp.c index b7b46d863bee..7aae83c108fd 100644 --- a/drivers/net/ethernet/intel/igc/igc_ptp.c +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -774,36 +774,43 @@ static void igc_ptp_tx_reg_to_stamp(struct igc_adapte= r *adapter, static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter) { struct igc_hw *hw =3D &adapter->hw; + u32 txstmpl_old; u64 regval; u32 mask; int i; =20 + /* Establish baseline of TXSTMPL_0 before checking TXTT_0. + * This baseline is used to detect if a new timestamp arrives in + * register 0 during the hardware bug workaround below. + */ + txstmpl_old =3D rd32(IGC_TXSTMPL); + mask =3D rd32(IGC_TSYNCTXCTL) & IGC_TSYNCTXCTL_TXTT_ANY; if (mask & IGC_TSYNCTXCTL_TXTT_0) { regval =3D rd32(IGC_TXSTMPL); regval |=3D (u64)rd32(IGC_TXSTMPH) << 32; } else { - /* There's a bug in the hardware that could cause - * missing interrupts for TX timestamping. The issue - * is that for new interrupts to be triggered, the - * IGC_TXSTMPH_0 register must be read. + /* TXTT_0 not set - register 0 has no new timestamp initially. + * + * Hardware bug: Future timestamp interrupts won't fire unless + * TXSTMPH_0 is read, even if the timestamp was captured in + * registers 1-3. * - * To avoid discarding a valid timestamp that just - * happened at the "wrong" time, we need to confirm - * that there was no timestamp captured, we do that by - * assuming that no two timestamps in sequence have - * the same nanosecond value. + * Workaround: Read TXSTMPH_0 here to enable future interrupts. + * However, this read clears TXTT_0. If a timestamp arrives in + * register 0 after checking TXTT_0 but before this read, it + * would be lost. * - * So, we read the "low" register, read the "high" - * register (to latch a new timestamp) and read the - * "low" register again, if "old" and "new" versions - * of the "low" register are different, a valid - * timestamp was captured, we can read the "high" - * register again. + * To detect this race: We saved a baseline read of TXSTMPL_0 + * before TXTT_0 check. After performing the workaround read of + * TXSTMPH_0, we read TXSTMPL_0 again. Since consecutive + * timestamps never share the same nanosecond value, a change + * between the baseline and new TXSTMPL_0 indicates a timestamp + * arrived during the race window. If so, read the complete + * timestamp. */ - u32 txstmpl_old, txstmpl_new; + u32 txstmpl_new; =20 - txstmpl_old =3D rd32(IGC_TXSTMPL); rd32(IGC_TXSTMPH); txstmpl_new =3D rd32(IGC_TXSTMPL); =20 @@ -818,7 +825,7 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *ada= pter) =20 done: /* Now that the problematic first register was handled, we can - * use retrieve the timestamps from the other registers + * retrieve the timestamps from the other registers * (starting from '1') with less complications. */ for (i =3D 1; i < IGC_MAX_TX_TSTAMP_REGS; i++) { diff --git a/export b/export new file mode 100644 index 000000000000..e69de29bb2d1 --=20 2.43.0