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);