Skip to content

Commit b03c49c

Browse files
vcgomesanguy11
authored andcommitted
igc: Save PTP time before a reset
Many TSN features depend on the internal PTP clock, so the internal PTP jumping when the adapter is reset can cause problems, usually in the form of "TX Hangs" warnings in the driver. The solution is to save the PTP time before a reset and restore it after the reset is done. The value of the PTP time is saved before a reset and we use the difference from CLOCK_MONOTONIC from reset time to now, to correct what's going to be the new PTP time. This is heavily inspired by commit bf4bf09 ("i40e: save PTP time before a device reset"). Signed-off-by: Vinicius Costa Gomes <[email protected]> Tested-by: Aaron Brown <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent e5f020a commit b03c49c

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

drivers/net/ethernet/intel/igc/igc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ struct igc_adapter {
215215
spinlock_t tmreg_lock;
216216
struct cyclecounter cc;
217217
struct timecounter tc;
218+
struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */
219+
ktime_t ptp_reset_start; /* Reset time in clock mono */
218220
};
219221

220222
void igc_up(struct igc_adapter *adapter);

drivers/net/ethernet/intel/igc/igc_main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3778,6 +3778,8 @@ void igc_down(struct igc_adapter *adapter)
37783778

37793779
set_bit(__IGC_DOWN, &adapter->state);
37803780

3781+
igc_ptp_suspend(adapter);
3782+
37813783
/* disable receives in the hardware */
37823784
rctl = rd32(IGC_RCTL);
37833785
wr32(IGC_RCTL, rctl & ~IGC_RCTL_EN);

drivers/net/ethernet/intel/igc/igc_ptp.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/pci.h>
99
#include <linux/ptp_classify.h>
1010
#include <linux/clocksource.h>
11+
#include <linux/ktime.h>
1112

1213
#define INCVALUE_MASK 0x7fffffff
1314
#define ISGN 0x80000000
@@ -500,6 +501,9 @@ void igc_ptp_init(struct igc_adapter *adapter)
500501
adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
501502
adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
502503

504+
adapter->prev_ptp_time = ktime_to_timespec64(ktime_get_real());
505+
adapter->ptp_reset_start = ktime_get();
506+
503507
adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,
504508
&adapter->pdev->dev);
505509
if (IS_ERR(adapter->ptp_clock)) {
@@ -511,6 +515,24 @@ void igc_ptp_init(struct igc_adapter *adapter)
511515
}
512516
}
513517

518+
static void igc_ptp_time_save(struct igc_adapter *adapter)
519+
{
520+
igc_ptp_read_i225(adapter, &adapter->prev_ptp_time);
521+
adapter->ptp_reset_start = ktime_get();
522+
}
523+
524+
static void igc_ptp_time_restore(struct igc_adapter *adapter)
525+
{
526+
struct timespec64 ts = adapter->prev_ptp_time;
527+
ktime_t delta;
528+
529+
delta = ktime_sub(ktime_get(), adapter->ptp_reset_start);
530+
531+
timespec64_add_ns(&ts, ktime_to_ns(delta));
532+
533+
igc_ptp_write_i225(adapter, &ts);
534+
}
535+
514536
/**
515537
* igc_ptp_suspend - Disable PTP work items and prepare for suspend
516538
* @adapter: Board private structure
@@ -527,6 +549,8 @@ void igc_ptp_suspend(struct igc_adapter *adapter)
527549
dev_kfree_skb_any(adapter->ptp_tx_skb);
528550
adapter->ptp_tx_skb = NULL;
529551
clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
552+
553+
igc_ptp_time_save(adapter);
530554
}
531555

532556
/**
@@ -576,9 +600,7 @@ void igc_ptp_reset(struct igc_adapter *adapter)
576600

577601
/* Re-initialize the timer. */
578602
if (hw->mac.type == igc_i225) {
579-
struct timespec64 ts64 = ktime_to_timespec64(ktime_get_real());
580-
581-
igc_ptp_write_i225(adapter, &ts64);
603+
igc_ptp_time_restore(adapter);
582604
} else {
583605
timecounter_init(&adapter->tc, &adapter->cc,
584606
ktime_to_ns(ktime_get_real()));

0 commit comments

Comments
 (0)