Thread (21 messages) flat view 21 messages, 5 authors, 2021-06-15

Re: [PATCH net-next 5/8] ice: register 1588 PTP clock device object for E810 devices

From: Jacob Keller <jacob.e.keller@intel.com>
Date: 2021-06-14 16:44:07


On 6/11/2021 2:18 PM, Jakub Kicinski wrote:
On Fri, 11 Jun 2021 09:19:57 -0700 Tony Nguyen wrote:
quoted
+static u64
+ice_ptp_read_src_clk_reg(struct ice_pf *pf, struct ptp_system_timestamp *sts)
+{
+	struct ice_hw *hw = &pf->hw;
+	u32 hi, lo, lo2;
+	u8 tmr_idx;
+
+	tmr_idx = ice_get_ptp_src_clock_index(hw);
+	/* Read the system timestamp pre PHC read */
+	if (sts)
+		ptp_read_system_prets(sts);
+
+	lo = rd32(hw, GLTSYN_TIME_L(tmr_idx));
+
+	/* Read the system timestamp post PHC read */
+	if (sts)
+		ptp_read_system_postts(sts);
+
+	hi = rd32(hw, GLTSYN_TIME_H(tmr_idx));
+	lo2 = rd32(hw, GLTSYN_TIME_L(tmr_idx));
+
+	if (lo2 < lo) {
+		/* if TIME_L rolled over read TIME_L again and update
+		 * system timestamps
+		 */
+		if (sts)
+			ptp_read_system_prets(sts);
+		lo = rd32(hw, GLTSYN_TIME_L(tmr_idx));
+		if (sts)
+			ptp_read_system_postts(sts);
ptp_read_system* helpers already check for NULL sts.
Hah. Yep, I knew that... and of course I forgot about it.
quoted
+static int ice_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm)
+{
+	struct ice_pf *pf = ptp_info_to_pf(info);
+	u64 freq, divisor = 1000000ULL;
+	struct ice_hw *hw = &pf->hw;
+	s64 incval, diff;
+	int neg_adj = 0;
+	int err;
+
+	incval = ICE_PTP_NOMINAL_INCVAL_E810;
+
+	if (scaled_ppm < 0) {
+		neg_adj = 1;
+		scaled_ppm = -scaled_ppm;
+	}
+
+	while ((u64)scaled_ppm > div_u64(U64_MAX, incval)) {
+		/* handle overflow by scaling down the scaled_ppm and
+		 * the divisor, losing some precision
+		 */
+		scaled_ppm >>= 2;
+		divisor >>= 2;
+	}
I have a question regarding ppm overflows.

We have the max_adj field in struct ptp_clock_info which is checked
against ppb, but ppb is a signed 32 bit and scaled_ppm is a long,
meaning values larger than S32_MAX << 16 / 1000 will overflow 
the ppb calculation, and therefore the check.
Hmmm.. I thought ppb was a s64, not an s32.

In general, I believe max_adj is usually capped at 1 billion anyways,
since it doesn't make sense to slow a clock by more than 1billioln ppb,
and increasing it more than that isn't really useful either.
Are we okay with that? Is my math off? Did I miss some part 
of the kernel which filters crazy high scaled_ppm/freq?

Since dialed_freq is updated regardless of return value of .adjfine 
the driver has no clear way to reject bad scaled_ppm>
I'm not sure. +Richard?
quoted
+	freq = (incval * (u64)scaled_ppm) >> 16;
+	diff = div_u64(freq, divisor);
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help