diff options
Diffstat (limited to 'drivers/net/ethernet/intel')
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 73 |
1 files changed, 40 insertions, 33 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 27a71fa26d3c..9f06896a049b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -113,12 +113,16 @@ * the sign bit. This register enables software to calculate frequency * adjustments and apply them directly to the clock rate. * - * The math for converting ppb into TIMINCA values is fairly straightforward. - * TIMINCA value = ( Base_Frequency * ppb ) / 1000000000ULL + * The math for converting scaled_ppm into TIMINCA values is fairly + * straightforward. * - * This assumes that ppb is never high enough to create a value bigger than - * TIMINCA's 31 bits can store. This is ensured by the stack. Calculating this - * value is also simple. + * TIMINCA value = ( Base_Frequency * scaled_ppm ) / 1000000ULL << 16 + * + * To avoid overflow, we simply use mul_u64_u64_div_u64. + * + * This assumes that scaled_ppm is never high enough to create a value bigger + * than TIMINCA's 31 bits can store. This is ensured by the stack, and is + * measured in parts per billion. Calculating this value is also simple. * Max ppb = ( Max Adjustment / Base Frequency ) / 1000000000ULL * * For the X550, the Max adjustment is +/- 0.5 ns, and the base frequency is @@ -433,45 +437,45 @@ static void ixgbe_ptp_convert_to_hwtstamp(struct ixgbe_adapter *adapter, } /** - * ixgbe_ptp_adjfreq_82599 + * ixgbe_ptp_adjfine_82599 * @ptp: the ptp clock structure - * @ppb: parts per billion adjustment from base + * @scaled_ppm: scaled parts per million adjustment from base + * + * Adjust the frequency of the ptp cycle counter by the + * indicated scaled_ppm from the base frequency. * - * adjust the frequency of the ptp cycle counter by the - * indicated ppb from the base frequency. + * Scaled parts per million is ppm with a 16-bit binary fractional field. */ -static int ixgbe_ptp_adjfreq_82599(struct ptp_clock_info *ptp, s32 ppb) +static int ixgbe_ptp_adjfine_82599(struct ptp_clock_info *ptp, long scaled_ppm) { struct ixgbe_adapter *adapter = container_of(ptp, struct ixgbe_adapter, ptp_caps); struct ixgbe_hw *hw = &adapter->hw; - u64 freq, incval; - u32 diff; + u64 incval, diff; int neg_adj = 0; - if (ppb < 0) { + if (scaled_ppm < 0) { neg_adj = 1; - ppb = -ppb; + scaled_ppm = -scaled_ppm; } smp_mb(); incval = READ_ONCE(adapter->base_incval); - freq = incval; - freq *= ppb; - diff = div_u64(freq, 1000000000ULL); + diff = mul_u64_u64_div_u64(incval, scaled_ppm, + 1000000ULL << 16); incval = neg_adj ? (incval - diff) : (incval + diff); switch (hw->mac.type) { case ixgbe_mac_X540: if (incval > 0xFFFFFFFFULL) - e_dev_warn("PTP ppb adjusted SYSTIME rate overflowed!\n"); + e_dev_warn("PTP scaled_ppm adjusted SYSTIME rate overflowed!\n"); IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, (u32)incval); break; case ixgbe_mac_82599EB: if (incval > 0x00FFFFFFULL) - e_dev_warn("PTP ppb adjusted SYSTIME rate overflowed!\n"); + e_dev_warn("PTP scaled_ppm adjusted SYSTIME rate overflowed!\n"); IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, BIT(IXGBE_INCPER_SHIFT_82599) | ((u32)incval & 0x00FFFFFFUL)); @@ -484,32 +488,35 @@ static int ixgbe_ptp_adjfreq_82599(struct ptp_clock_info *ptp, s32 ppb) } /** - * ixgbe_ptp_adjfreq_X550 + * ixgbe_ptp_adjfine_X550 * @ptp: the ptp clock structure - * @ppb: parts per billion adjustment from base + * @scaled_ppm: scaled parts per million adjustment from base * - * adjust the frequency of the SYSTIME registers by the indicated ppb from base - * frequency + * Adjust the frequency of the SYSTIME registers by the indicated scaled_ppm + * from base frequency. + * + * Scaled parts per million is ppm with a 16-bit binary fractional field. */ -static int ixgbe_ptp_adjfreq_X550(struct ptp_clock_info *ptp, s32 ppb) +static int ixgbe_ptp_adjfine_X550(struct ptp_clock_info *ptp, long scaled_ppm) { struct ixgbe_adapter *adapter = container_of(ptp, struct ixgbe_adapter, ptp_caps); struct ixgbe_hw *hw = &adapter->hw; int neg_adj = 0; - u64 rate = IXGBE_X550_BASE_PERIOD; + u64 rate; u32 inca; - if (ppb < 0) { + if (scaled_ppm < 0) { neg_adj = 1; - ppb = -ppb; + scaled_ppm = -scaled_ppm; } - rate *= ppb; - rate = div_u64(rate, 1000000000ULL); + + rate = mul_u64_u64_div_u64(IXGBE_X550_BASE_PERIOD, scaled_ppm, + 1000000ULL << 16); /* warn if rate is too large */ if (rate >= INCVALUE_MASK) - e_dev_warn("PTP ppb adjusted SYSTIME rate overflowed!\n"); + e_dev_warn("PTP scaled_ppm adjusted SYSTIME rate overflowed!\n"); inca = rate & INCVALUE_MASK; if (neg_adj) @@ -1355,7 +1362,7 @@ static long ixgbe_ptp_create_clock(struct ixgbe_adapter *adapter) adapter->ptp_caps.n_ext_ts = 0; adapter->ptp_caps.n_per_out = 0; adapter->ptp_caps.pps = 1; - adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq_82599; + adapter->ptp_caps.adjfine = ixgbe_ptp_adjfine_82599; adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; adapter->ptp_caps.gettimex64 = ixgbe_ptp_gettimex; adapter->ptp_caps.settime64 = ixgbe_ptp_settime; @@ -1372,7 +1379,7 @@ static long ixgbe_ptp_create_clock(struct ixgbe_adapter *adapter) adapter->ptp_caps.n_ext_ts = 0; adapter->ptp_caps.n_per_out = 0; adapter->ptp_caps.pps = 0; - adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq_82599; + adapter->ptp_caps.adjfine = ixgbe_ptp_adjfine_82599; adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; adapter->ptp_caps.gettimex64 = ixgbe_ptp_gettimex; adapter->ptp_caps.settime64 = ixgbe_ptp_settime; @@ -1388,7 +1395,7 @@ static long ixgbe_ptp_create_clock(struct ixgbe_adapter *adapter) adapter->ptp_caps.n_ext_ts = 0; adapter->ptp_caps.n_per_out = 0; adapter->ptp_caps.pps = 1; - adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq_X550; + adapter->ptp_caps.adjfine = ixgbe_ptp_adjfine_X550; adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; adapter->ptp_caps.gettimex64 = ixgbe_ptp_gettimex; adapter->ptp_caps.settime64 = ixgbe_ptp_settime; |