hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/drivers/net/ethernet/intel/i40e/i40e_ptp.c
....@@ -11,13 +11,14 @@
1111 * operate with the nanosecond field directly without fear of overflow.
1212 *
1313 * Much like the 82599, the update period is dependent upon the link speed:
14
- * At 40Gb link or no link, the period is 1.6ns.
15
- * At 10Gb link, the period is multiplied by 2. (3.2ns)
14
+ * At 40Gb, 25Gb, or no link, the period is 1.6ns.
15
+ * At 10Gb or 5Gb link, the period is multiplied by 2. (3.2ns)
1616 * At 1Gb link, the period is multiplied by 20. (32ns)
1717 * 1588 functionality is not supported at 100Mbps.
1818 */
1919 #define I40E_PTP_40GB_INCVAL 0x0199999999ULL
2020 #define I40E_PTP_10GB_INCVAL_MULT 2
21
+#define I40E_PTP_5GB_INCVAL_MULT 2
2122 #define I40E_PTP_1GB_INCVAL_MULT 20
2223
2324 #define I40E_PRTTSYN_CTL1_TSYNTYPE_V1 BIT(I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
....@@ -28,19 +29,23 @@
2829 * i40e_ptp_read - Read the PHC time from the device
2930 * @pf: Board private structure
3031 * @ts: timespec structure to hold the current time value
32
+ * @sts: structure to hold the system time before and after reading the PHC
3133 *
3234 * This function reads the PRTTSYN_TIME registers and stores them in a
3335 * timespec. However, since the registers are 64 bits of nanoseconds, we must
3436 * convert the result to a timespec before we can return.
3537 **/
36
-static void i40e_ptp_read(struct i40e_pf *pf, struct timespec64 *ts)
38
+static void i40e_ptp_read(struct i40e_pf *pf, struct timespec64 *ts,
39
+ struct ptp_system_timestamp *sts)
3740 {
3841 struct i40e_hw *hw = &pf->hw;
3942 u32 hi, lo;
4043 u64 ns;
4144
4245 /* The timer latches on the lowest register read. */
46
+ ptp_read_system_prets(sts);
4347 lo = rd32(hw, I40E_PRTTSYN_TIME_L);
48
+ ptp_read_system_postts(sts);
4449 hi = rd32(hw, I40E_PRTTSYN_TIME_H);
4550
4651 ns = (((u64)hi) << 32) | lo;
....@@ -136,18 +141,18 @@
136141 * @ptp: The PTP clock structure
137142 * @delta: Offset in nanoseconds to adjust the PHC time by
138143 *
139
- * Adjust the frequency of the PHC by the indicated parts per billion from the
140
- * base frequency.
144
+ * Adjust the current clock time by a delta specified in nanoseconds.
141145 **/
142146 static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
143147 {
144148 struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
145
- struct timespec64 now;
149
+ struct timespec64 now, then;
146150
151
+ then = ns_to_timespec64(delta);
147152 mutex_lock(&pf->tmreg_lock);
148153
149
- i40e_ptp_read(pf, &now);
150
- timespec64_add_ns(&now, delta);
154
+ i40e_ptp_read(pf, &now, NULL);
155
+ now = timespec64_add(now, then);
151156 i40e_ptp_write(pf, (const struct timespec64 *)&now);
152157
153158 mutex_unlock(&pf->tmreg_lock);
....@@ -156,19 +161,21 @@
156161 }
157162
158163 /**
159
- * i40e_ptp_gettime - Get the time of the PHC
164
+ * i40e_ptp_gettimex - Get the time of the PHC
160165 * @ptp: The PTP clock structure
161166 * @ts: timespec structure to hold the current time value
167
+ * @sts: structure to hold the system time before and after reading the PHC
162168 *
163169 * Read the device clock and return the correct value on ns, after converting it
164170 * into a timespec struct.
165171 **/
166
-static int i40e_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
172
+static int i40e_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts,
173
+ struct ptp_system_timestamp *sts)
167174 {
168175 struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
169176
170177 mutex_lock(&pf->tmreg_lock);
171
- i40e_ptp_read(pf, ts);
178
+ i40e_ptp_read(pf, ts, sts);
172179 mutex_unlock(&pf->tmreg_lock);
173180
174181 return 0;
....@@ -253,7 +260,6 @@
253260 /**
254261 * i40e_ptp_rx_hang - Detect error case when Rx timestamp registers are hung
255262 * @pf: The PF private data structure
256
- * @vsi: The VSI with the rings relevant to 1588
257263 *
258264 * This watchdog task is scheduled to detect error case where hardware has
259265 * dropped an Rx packet that was timestamped when the ring is full. The
....@@ -460,6 +466,9 @@
460466 case I40E_LINK_SPEED_10GB:
461467 mult = I40E_PTP_10GB_INCVAL_MULT;
462468 break;
469
+ case I40E_LINK_SPEED_5GB:
470
+ mult = I40E_PTP_5GB_INCVAL_MULT;
471
+ break;
463472 case I40E_LINK_SPEED_1GB:
464473 mult = I40E_PTP_1GB_INCVAL_MULT;
465474 break;
....@@ -580,7 +589,7 @@
580589 case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
581590 if (!(pf->hw_features & I40E_HW_PTP_L4_CAPABLE))
582591 return -ERANGE;
583
- /* fall through */
592
+ fallthrough;
584593 case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
585594 case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
586595 case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
....@@ -694,7 +703,7 @@
694703 if (!IS_ERR_OR_NULL(pf->ptp_clock))
695704 return 0;
696705
697
- strncpy(pf->ptp_caps.name, i40e_driver_name,
706
+ strlcpy(pf->ptp_caps.name, i40e_driver_name,
698707 sizeof(pf->ptp_caps.name) - 1);
699708 pf->ptp_caps.owner = THIS_MODULE;
700709 pf->ptp_caps.max_adj = 999999999;
....@@ -702,7 +711,7 @@
702711 pf->ptp_caps.pps = 0;
703712 pf->ptp_caps.adjfreq = i40e_ptp_adjfreq;
704713 pf->ptp_caps.adjtime = i40e_ptp_adjtime;
705
- pf->ptp_caps.gettime64 = i40e_ptp_gettime;
714
+ pf->ptp_caps.gettimex64 = i40e_ptp_gettimex;
706715 pf->ptp_caps.settime64 = i40e_ptp_settime;
707716 pf->ptp_caps.enable = i40e_ptp_feature_enable;
708717
....@@ -718,7 +727,54 @@
718727 pf->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
719728 pf->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
720729
730
+ /* Set the previous "reset" time to the current Kernel clock time */
731
+ ktime_get_real_ts64(&pf->ptp_prev_hw_time);
732
+ pf->ptp_reset_start = ktime_get();
733
+
721734 return 0;
735
+}
736
+
737
+/**
738
+ * i40e_ptp_save_hw_time - Save the current PTP time as ptp_prev_hw_time
739
+ * @pf: Board private structure
740
+ *
741
+ * Read the current PTP time and save it into pf->ptp_prev_hw_time. This should
742
+ * be called at the end of preparing to reset, just before hardware reset
743
+ * occurs, in order to preserve the PTP time as close as possible across
744
+ * resets.
745
+ */
746
+void i40e_ptp_save_hw_time(struct i40e_pf *pf)
747
+{
748
+ /* don't try to access the PTP clock if it's not enabled */
749
+ if (!(pf->flags & I40E_FLAG_PTP))
750
+ return;
751
+
752
+ i40e_ptp_gettimex(&pf->ptp_caps, &pf->ptp_prev_hw_time, NULL);
753
+ /* Get a monotonic starting time for this reset */
754
+ pf->ptp_reset_start = ktime_get();
755
+}
756
+
757
+/**
758
+ * i40e_ptp_restore_hw_time - Restore the ptp_prev_hw_time + delta to PTP regs
759
+ * @pf: Board private structure
760
+ *
761
+ * Restore the PTP hardware clock registers. We previously cached the PTP
762
+ * hardware time as pf->ptp_prev_hw_time. To be as accurate as possible,
763
+ * update this value based on the time delta since the time was saved, using
764
+ * CLOCK_MONOTONIC (via ktime_get()) to calculate the time difference.
765
+ *
766
+ * This ensures that the hardware clock is restored to nearly what it should
767
+ * have been if a reset had not occurred.
768
+ */
769
+void i40e_ptp_restore_hw_time(struct i40e_pf *pf)
770
+{
771
+ ktime_t delta = ktime_sub(ktime_get(), pf->ptp_reset_start);
772
+
773
+ /* Update the previous HW time with the ktime delta */
774
+ timespec64_add_ns(&pf->ptp_prev_hw_time, ktime_to_ns(delta));
775
+
776
+ /* Restore the hardware clock registers */
777
+ i40e_ptp_settime(&pf->ptp_caps, &pf->ptp_prev_hw_time);
722778 }
723779
724780 /**
....@@ -728,6 +784,11 @@
728784 * This function sets device up for 1588 support. The first time it is run, it
729785 * will create a PHC clock device. It does not create a clock device if one
730786 * already exists. It also reconfigures the device after a reset.
787
+ *
788
+ * The first time a clock is created, i40e_ptp_create_clock will set
789
+ * pf->ptp_prev_hw_time to the current system time. During resets, it is
790
+ * expected that this timespec will be set to the last known PTP clock time,
791
+ * in order to preserve the clock time as close as possible across a reset.
731792 **/
732793 void i40e_ptp_init(struct i40e_pf *pf)
733794 {
....@@ -759,7 +820,6 @@
759820 dev_err(&pf->pdev->dev, "%s: ptp_clock_register failed\n",
760821 __func__);
761822 } else if (pf->ptp_clock) {
762
- struct timespec64 ts;
763823 u32 regval;
764824
765825 if (pf->hw.debug_mask & I40E_DEBUG_LAN)
....@@ -780,9 +840,8 @@
780840 /* reset timestamping mode */
781841 i40e_ptp_set_timestamp_mode(pf, &pf->tstamp_config);
782842
783
- /* Set the clock value. */
784
- ts = ktime_to_timespec64(ktime_get_real());
785
- i40e_ptp_settime(&pf->ptp_caps, &ts);
843
+ /* Restore the clock time based on last known value */
844
+ i40e_ptp_restore_hw_time(pf);
786845 }
787846 }
788847