RE: [Intel-wired-lan] [PATCH iwl-net v1] igc: fix race condition in TX timestamp read for register 0

From: Loktionov, Aleksandr

Date: Fri Sep 19 2025 - 15:34:58 EST




> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@xxxxxxxxxx> On Behalf
> Of Chwee-Lin Choong
> Sent: Thursday, September 18, 2025 8:38 PM
> To: Nguyen, Anthony L <anthony.l.nguyen@xxxxxxxxx>; Kitszel,
> Przemyslaw <przemyslaw.kitszel@xxxxxxxxx>; Andrew Lunn
> <andrew+netdev@xxxxxxx>; David S . Miller <davem@xxxxxxxxxxxxx>; Eric
> Dumazet <edumazet@xxxxxxxxxx>; Jakub Kicinski <kuba@xxxxxxxxxx>; Paolo
> Abeni <pabeni@xxxxxxxxxx>; Richard Cochran <richardcochran@xxxxxxxxx>;
> Gomes, Vinicius <vinicius.gomes@xxxxxxxxx>
> Cc: intel-wired-lan@xxxxxxxxxxxxxxxx; netdev@xxxxxxxxxxxxxxx; linux-
> kernel@xxxxxxxxxxxxxxx; Shalev, Avi <avi.shalev@xxxxxxxxx>; Song,
> Yoong Siang <yoong.siang.song@xxxxxxxxx>
> Subject: [Intel-wired-lan] [PATCH iwl-net v1] igc: fix race condition
> in TX timestamp read for register 0
>
> The current HW bug workaround checks the TXTT_0 ready bit first, then
> reads LOW -> HIGH -> LOW from register 0 to detect if a timestamp was
> captured.
>
> This sequence has a race: if a new timestamp is latched after reading
> the TXTT mask but before the first LOW read, both old and new
> timestamp match, causing the driver to drop a valid timestamp.
>
> Fix by reading the LOW register first, then the TXTT mask, so a newly
> latched timestamp will always be detected.
>
> This fix also prevents TX unit hangs observed under heavy timestamping
> load.
>
> Fixes: c789ad7cbebc ("igc: Work around HW bug causing missing
> timestamps")
> Suggested-by: Avi Shalev <avi.shalev@xxxxxxxxx>
> Signed-off-by: Song Yoong Siang <yoong.siang.song@xxxxxxxxx>
> Signed-off-by: Chwee-Lin Choong <chwee.lin.choong@xxxxxxxxx>
> ---
> drivers/net/ethernet/intel/igc/igc_ptp.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c
> b/drivers/net/ethernet/intel/igc/igc_ptp.c
> index b7b46d863bee..930486b02fc1 100644
> --- a/drivers/net/ethernet/intel/igc/igc_ptp.c
> +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c
> @@ -774,10 +774,17 @@ static void igc_ptp_tx_reg_to_stamp(struct
> igc_adapter *adapter, static void igc_ptp_tx_hwtstamp(struct
> igc_adapter *adapter) {
> struct igc_hw *hw = &adapter->hw;
> + u32 txstmpl_old;
> u64 regval;
> u32 mask;
> int i;
>
> + /* Read the "low" register 0 first to establish a baseline
> value.
> + * This avoids a race where a new timestamp could be latched
> + * after checking the TXTT mask.
> + */
> + txstmpl_old = rd32(IGC_TXSTMPL);
> +
> mask = rd32(IGC_TSYNCTXCTL) & IGC_TSYNCTXCTL_TXTT_ANY;
> if (mask & IGC_TSYNCTXCTL_TXTT_0) {
> regval = rd32(IGC_TXSTMPL);
> @@ -801,9 +808,8 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter
> *adapter)
> * timestamp was captured, we can read the "high"
> * register again.
> */
> - u32 txstmpl_old, txstmpl_new;
> + u32 txstmpl_new;
>
> - txstmpl_old = rd32(IGC_TXSTMPL);
> rd32(IGC_TXSTMPH);
> txstmpl_new = rd32(IGC_TXSTMPL);
>
> --
> 2.42.0

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@xxxxxxxxx>