> -----Original Message-----
> From: Intel-wired-lan <[email protected]> On Behalf
> Of Kurt Kanzenbach
> Sent: Thursday, February 5, 2026 8:55 AM
> To: Nguyen, Anthony L <[email protected]>; Kitszel,
> Przemyslaw <[email protected]>
> Cc: Paul Menzel <[email protected]>; Vadim Fedorenko
> <[email protected]>; Gomes, Vinicius
> <[email protected]>; [email protected]; Richard Cochran
> <[email protected]>; Kurt Kanzenbach <[email protected]>;
> [email protected]; Andrew Lunn <[email protected]>;
> Eric Dumazet <[email protected]>; [email protected];
> Keller, Jacob E <[email protected]>; Jakub Kicinski
> <[email protected]>; Paolo Abeni <[email protected]>; David S. Miller
> <[email protected]>; Sebastian Andrzej Siewior
> <[email protected]>
> Subject: [Intel-wired-lan] [PATCH iwl-next v3] igb: Retrieve Tx
> timestamp directly from interrupt for i210
>
> Retrieve Tx timestamp directly from interrupt handler for i210.
>
> The current implementation uses schedule_work() which is executed by
> the system work queue to retrieve Tx timestamps. This increases
> latency and can lead to timeouts in case of heavy system load. i210 is
> often used in industrial systems, where timestamp timeouts can be
> fatal.
>
> Therefore, fetch the timestamp directly from the interrupt handler.
>
> The work queue code stays for all other NICs supported by igb.
>
> Tested on Intel i210 and i350.
>
> Signed-off-by: Kurt Kanzenbach <[email protected]>
> ---
> Changes in v3:
> - Switch back to IRQ, but for i210 only
> - Keep kworker for all other NICs like i350 (Miroslav)
> - Link to v2: https://lore.kernel.org/r/20250822-igb_irq_ts-v2-1-
> [email protected]
>
> Changes in v2:
> - Switch from IRQ to PTP aux worker due to NTP performance regression
> (Miroslav)
> - Link to v1: https://lore.kernel.org/r/20250815-igb_irq_ts-v1-1-
> [email protected]
> ---
> drivers/net/ethernet/intel/igb/igb.h | 1 +
> drivers/net/ethernet/intel/igb/igb_main.c | 5 ++++-
> drivers/net/ethernet/intel/igb/igb_ptp.c | 22 ++++++++++++++++++++++
> 3 files changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/intel/igb/igb.h
> b/drivers/net/ethernet/intel/igb/igb.h
> index 0fff1df81b7b..1de29670784e 100644
> --- a/drivers/net/ethernet/intel/igb/igb.h
> +++ b/drivers/net/ethernet/intel/igb/igb.h
> @@ -776,6 +776,7 @@ int igb_ptp_hwtstamp_get(struct net_device
> *netdev, int igb_ptp_hwtstamp_set(struct net_device *netdev,
> struct kernel_hwtstamp_config *config,
> struct netlink_ext_ack *extack);
> +void igb_ptp_tx_tstamp_event(struct igb_adapter *adapter);
> void igb_set_flag_queue_pairs(struct igb_adapter *, const u32);
> unsigned int igb_get_max_rss_queues(struct igb_adapter *); #ifdef
> CONFIG_IGB_HWMON diff --git
> a/drivers/net/ethernet/intel/igb/igb_main.c
> b/drivers/net/ethernet/intel/igb/igb_main.c
> index dbea37269d2c..d0d9245e6d72 100644
> --- a/drivers/net/ethernet/intel/igb/igb_main.c
> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> @@ -7078,7 +7078,10 @@ static void igb_tsync_interrupt(struct
> igb_adapter *adapter)
>
> if (tsicr & E1000_TSICR_TXTS) {
> /* retrieve hardware timestamp */
> - schedule_work(&adapter->ptp_tx_work);
> + if (hw->mac.type == e1000_i210)
> + igb_ptp_tx_tstamp_event(adapter); <-Called from IRQ!
> + else
> + schedule_work(&adapter->ptp_tx_work);
> }
>
> if (tsicr & TSINTR_TT0)
> diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c
> b/drivers/net/ethernet/intel/igb/igb_ptp.c
> index bd85d02ecadd..8c8f2b8615f7 100644
> --- a/drivers/net/ethernet/intel/igb/igb_ptp.c
> +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
> @@ -796,6 +796,28 @@ static int igb_ptp_verify_pin(struct
> ptp_clock_info *ptp, unsigned int pin,
> return 0;
> }
>
> +/**
> + * igb_ptp_tx_tstamp_event
> + * @adapter: pointer to igb adapter
> + *
> + * This function checks the TSYNCTXCTL valid bit and stores the Tx
> +hardware
> + * timestamp at the current skb.
> + **/
> +void igb_ptp_tx_tstamp_event(struct igb_adapter *adapter) {
> + struct e1000_hw *hw = &adapter->hw;
> + u32 tsynctxctl;
> +
> + if (!adapter->ptp_tx_skb)
> + return;
> +
> + tsynctxctl = rd32(E1000_TSYNCTXCTL);
> + if (WARN_ON_ONCE(!(tsynctxctl & E1000_TSYNCTXCTL_VALID)))
> + return;
> +
> + igb_ptp_tx_hwtstamp(adapter); <-Calls existing function designed for
> work queue!
skb_tstamp_tx() can sleep
Smells like sleep-in-atomic isn't it?
> +}
> +
> /**
> * igb_ptp_tx_work
> * @work: pointer to work struct
>
> ---
> base-commit: e07d0d30939990da377672ef49ca09763b4fbc79
> change-id: 20250813-igb_irq_ts-1aa77cc7b4cb
>
> Best regards,
> --
> Kurt Kanzenbach <[email protected]>