All of lore.kernel.org
 help / color / mirror / Atom feed
* [Intel-wired-lan] [net-next PATCH 0/7] intel: ptp: convert .adjfreq to .adjfine
@ 2022-07-21 21:29 Jacob Keller
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 1/7] ice: implement adjfine with mul_u64_u64_div_u64 Jacob Keller
                   ` (7 more replies)
  0 siblings, 8 replies; 16+ messages in thread
From: Jacob Keller @ 2022-07-21 21:29 UTC (permalink / raw)
  To: Intel Wired LAN

Convert all of the Intel drivers with PTP support to the newer .adjfine
implementation which uses scaled parts per million.

This improves the precision of the frequency adjustments by taking advantage
of the full scaled parts per million input coming from user space.

In addition, all implementations are converted to using the
mul_u64_u64_div_u64 function which better handles the intermediate value.
This function supports architecture specific instructions where possible to
avoid loss of precision if the normal 64-bit multiplication would overflow.

Of note, the i40e implementation is now able to avoid loss of precision on
slower link speeds by taking advantage of this to multiply by the link speed
factor first. This results in a significantly more precise adjustment by
allowing the calculation to impact the lower bits.

This also gets us a step closer to being able to remove the .adjfreq
entirely by removing its use from many drivers.

I plan to follow this up with a series to update the drivers from other
vendors and drop the .adjfreq implementation entirely.

Jacob Keller (7):
  ice: implement adjfine with mul_u64_u64_div_u64
  e1000e: remove unnecessary range check in e1000e_phc_adjfreq
  e1000e: convert .adjfreq to .adjfine
  i40e: use mul_u64_u64_div_u64 for PTP frequency calculation
  i40e: convert .adjfreq to .adjfine
  ixgbe: convert .adjfreq to .adjfine
  igb: convert .adjfreq to .adjfine

 drivers/net/ethernet/intel/e1000e/e1000.h    |  2 +-
 drivers/net/ethernet/intel/e1000e/netdev.c   |  4 +-
 drivers/net/ethernet/intel/e1000e/ptp.c      | 18 +++--
 drivers/net/ethernet/intel/i40e/i40e_ptp.c   | 35 ++++------
 drivers/net/ethernet/intel/ice/ice_ptp.c     | 16 +----
 drivers/net/ethernet/intel/igb/igb_ptp.c     | 15 ++--
 drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 73 +++++++++++---------
 7 files changed, 75 insertions(+), 88 deletions(-)


base-commit: 9f055d4106bdefd5a533316c1d3dc3b5e9821b9a
-- 
2.35.1.456.ga9c7032d4631

_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Intel-wired-lan] [net-next PATCH 1/7] ice: implement adjfine with mul_u64_u64_div_u64
  2022-07-21 21:29 [Intel-wired-lan] [net-next PATCH 0/7] intel: ptp: convert .adjfreq to .adjfine Jacob Keller
@ 2022-07-21 21:29 ` Jacob Keller
  2022-07-26 12:48   ` G, GurucharanX
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 1/1] igb: convert .adjfreq to .adjfine Jacob Keller
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Jacob Keller @ 2022-07-21 21:29 UTC (permalink / raw)
  To: Intel Wired LAN

The PTP frequency adjustment code needs to determine an appropriate
adjustment given an input scaled_ppm adjustment.

We calculate the adjustment to the register by multiplying the base
(nominal) increment value by the scaled_ppm and then dividing by the
scaled one million value.

For very large adjustments, this might overflow. To avoid this, both the
scaled_ppm and divisor values are downshifted.

We can avoid that on X86 architectures by using mul_u64_u64_div_u64. This
helper function will perform the multiplication and division with 128bit
intermediate values. We know that scaled_ppm is never larger than the
divisor so this operation will never result in an overflow.

This improves the accuracy of the calculations for large adjustment values
on X86. It is likely an improvement on other architectures as well because
the default implementation of mul_u64_u64_div_u64 is smarter than the
original approach taken in the ice code.

Additionally, this implementation is easier to read, using fewer local
variables and lines of code to implement.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_ptp.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 29c7a0ccb3c4..72b663108a4a 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -1102,9 +1102,8 @@ static void ice_ptp_reset_phy_timestamping(struct ice_pf *pf)
 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;
+	u64 incval, diff;
 	int neg_adj = 0;
 	int err;
 
@@ -1115,17 +1114,8 @@ static int ice_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm)
 		scaled_ppm = -scaled_ppm;
 	}
 
-	while ((u64)scaled_ppm > div64_u64(U64_MAX, incval)) {
-		/* handle overflow by scaling down the scaled_ppm and
-		 * the divisor, losing some precision
-		 */
-		scaled_ppm >>= 2;
-		divisor >>= 2;
-	}
-
-	freq = (incval * (u64)scaled_ppm) >> 16;
-	diff = div_u64(freq, divisor);
-
+	diff = mul_u64_u64_div_u64(incval, (u64)scaled_ppm,
+				   1000000ULL << 16);
 	if (neg_adj)
 		incval -= diff;
 	else
-- 
2.35.1.456.ga9c7032d4631

_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Intel-wired-lan] [net-next PATCH 1/1] igb: convert .adjfreq to .adjfine
  2022-07-21 21:29 [Intel-wired-lan] [net-next PATCH 0/7] intel: ptp: convert .adjfreq to .adjfine Jacob Keller
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 1/7] ice: implement adjfine with mul_u64_u64_div_u64 Jacob Keller
@ 2022-07-21 21:29 ` Jacob Keller
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 2/7] e1000e: remove unnecessary range check in e1000e_phc_adjfreq Jacob Keller
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 16+ messages in thread
From: Jacob Keller @ 2022-07-21 21:29 UTC (permalink / raw)
  To: Intel Wired LAN

The 82576 PTP implementation still uses .adjfreq instead of using the newer
.adjfine.

This implementation uses a pre-simplified calculation since the base
increment value for the 82576 is just 16 * 2^19. Converting this into
scaled_ppm is tricky, and makes the intent a bit less clear.

Simply convert to the normal flow of multiplying the base increment value
by the scaled_ppm and then dividing by 1000000ULL << 16. This can be
implemented using mul_u64_u64_div_u64 which can avoid the possible overflow
that might occur for large adjustments.

Use of .adjfine can improve the precision of small adjustments and gets us
one driver closer to removing the old implementation from the kernel
entirely.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
 drivers/net/ethernet/intel/igb/igb_ptp.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index 02fec948ce64..15e57460e19e 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -190,7 +190,7 @@ static void igb_ptp_systim_to_hwtstamp(struct igb_adapter *adapter,
 }
 
 /* PTP clock operations */
-static int igb_ptp_adjfreq_82576(struct ptp_clock_info *ptp, s32 ppb)
+static int igb_ptp_adjfine_82576(struct ptp_clock_info *ptp, long scaled_ppm)
 {
 	struct igb_adapter *igb = container_of(ptp, struct igb_adapter,
 					       ptp_caps);
@@ -199,15 +199,14 @@ static int igb_ptp_adjfreq_82576(struct ptp_clock_info *ptp, s32 ppb)
 	u64 rate;
 	u32 incvalue;
 
-	if (ppb < 0) {
+	if (scaled_ppm < 0) {
 		neg_adj = 1;
-		ppb = -ppb;
+		scaled_ppm = -scaled_ppm;
 	}
-	rate = ppb;
-	rate <<= 14;
-	rate = div_u64(rate, 1953125);
 
-	incvalue = 16 << IGB_82576_TSYNC_SHIFT;
+	incvalue = INCVALUE_82576;
+	rate = mul_u64_u64_div_u64(incvalue, (u64)scaled_ppm,
+				   1000000ULL << 16);
 
 	if (neg_adj)
 		incvalue -= rate;
@@ -1347,7 +1346,7 @@ void igb_ptp_init(struct igb_adapter *adapter)
 		adapter->ptp_caps.max_adj = 999999881;
 		adapter->ptp_caps.n_ext_ts = 0;
 		adapter->ptp_caps.pps = 0;
-		adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82576;
+		adapter->ptp_caps.adjfine = igb_ptp_adjfine_82576;
 		adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576;
 		adapter->ptp_caps.gettimex64 = igb_ptp_gettimex_82576;
 		adapter->ptp_caps.settime64 = igb_ptp_settime_82576;
-- 
2.35.1.456.ga9c7032d4631

_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Intel-wired-lan] [net-next PATCH 2/7] e1000e: remove unnecessary range check in e1000e_phc_adjfreq
  2022-07-21 21:29 [Intel-wired-lan] [net-next PATCH 0/7] intel: ptp: convert .adjfreq to .adjfine Jacob Keller
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 1/7] ice: implement adjfine with mul_u64_u64_div_u64 Jacob Keller
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 1/1] igb: convert .adjfreq to .adjfine Jacob Keller
@ 2022-07-21 21:29 ` Jacob Keller
  2022-07-25  4:44   ` naamax.meir
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 3/7] e1000e: convert .adjfreq to .adjfine Jacob Keller
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Jacob Keller @ 2022-07-21 21:29 UTC (permalink / raw)
  To: Intel Wired LAN

The e1000e_phc_adjfreq function validates that the input delta is within
the maximum range. This is already handled by the core PTP code and this is
a duplicate and thus unnecessary check. It also complicates refactoring to
use the newer .adjfine implementation, where the input is no longer
specified in parts per billion. Remove the range validation check.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
 drivers/net/ethernet/intel/e1000e/ptp.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c
index eb5c014c02fb..432e04ce8c4e 100644
--- a/drivers/net/ethernet/intel/e1000e/ptp.c
+++ b/drivers/net/ethernet/intel/e1000e/ptp.c
@@ -33,9 +33,6 @@ static int e1000e_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
 	u32 timinca, incvalue;
 	s32 ret_val;
 
-	if ((delta > ptp->max_adj) || (delta <= -1000000000))
-		return -EINVAL;
-
 	if (delta < 0) {
 		neg_adj = true;
 		delta = -delta;
-- 
2.35.1.456.ga9c7032d4631

_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Intel-wired-lan] [net-next PATCH 3/7] e1000e: convert .adjfreq to .adjfine
  2022-07-21 21:29 [Intel-wired-lan] [net-next PATCH 0/7] intel: ptp: convert .adjfreq to .adjfine Jacob Keller
                   ` (2 preceding siblings ...)
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 2/7] e1000e: remove unnecessary range check in e1000e_phc_adjfreq Jacob Keller
@ 2022-07-21 21:29 ` Jacob Keller
  2022-07-25 11:37   ` naamax.meir
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 4/7] i40e: use mul_u64_u64_div_u64 for PTP frequency calculation Jacob Keller
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Jacob Keller @ 2022-07-21 21:29 UTC (permalink / raw)
  To: Intel Wired LAN

The PTP implementation for the e1000e driver uses the older .adjfreq
method. This method takes an adjustment in parts per billion. The newer
.adjfine implementation uses scaled_ppm. The use of scaled_ppm allows for
finer grained adjustments and is preferred over using the older
implementation.

Make use of mul_u64_u64_div_u64 in order to handle possible overflow of the
multiplication used to calculate the desired adjustment to the hardware
increment value.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
 drivers/net/ethernet/intel/e1000e/e1000.h  |  2 +-
 drivers/net/ethernet/intel/e1000e/netdev.c |  4 ++--
 drivers/net/ethernet/intel/e1000e/ptp.c    | 15 ++++++++-------
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index 8d06c9d8ff8b..e8a9a9610ac6 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -329,7 +329,7 @@ struct e1000_adapter {
 	struct ptp_clock *ptp_clock;
 	struct ptp_clock_info ptp_clock_info;
 	struct pm_qos_request pm_qos_req;
-	s32 ptp_delta;
+	long ptp_delta;
 
 	u16 eee_advert;
 };
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 70d933f52e93..321f2a95ae3a 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -3922,9 +3922,9 @@ static void e1000e_systim_reset(struct e1000_adapter *adapter)
 	if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP))
 		return;
 
-	if (info->adjfreq) {
+	if (info->adjfine) {
 		/* restore the previous ptp frequency delta */
-		ret_val = info->adjfreq(info, adapter->ptp_delta);
+		ret_val = info->adjfine(info, adapter->ptp_delta);
 	} else {
 		/* set the default base frequency if no adjustment possible */
 		ret_val = e1000e_get_base_timinca(adapter, &timinca);
diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c
index 432e04ce8c4e..0e488e4fa5c1 100644
--- a/drivers/net/ethernet/intel/e1000e/ptp.c
+++ b/drivers/net/ethernet/intel/e1000e/ptp.c
@@ -15,14 +15,16 @@
 #endif
 
 /**
- * e1000e_phc_adjfreq - adjust the frequency of the hardware clock
+ * e1000e_phc_adjfine - adjust the frequency of the hardware clock
  * @ptp: ptp clock structure
- * @delta: Desired frequency change in parts per billion
+ * @delta: Desired frequency chance in scaled parts per million
  *
  * Adjust the frequency of the PHC cycle counter by the indicated delta from
  * the base frequency.
+ *
+ * Scaled parts per million is ppm but with a 16 bit binary fractional field.
  **/
-static int e1000e_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
+static int e1000e_phc_adjfine(struct ptp_clock_info *ptp, long delta)
 {
 	struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter,
 						     ptp_clock_info);
@@ -47,9 +49,8 @@ static int e1000e_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
 
 	incvalue = timinca & E1000_TIMINCA_INCVALUE_MASK;
 
-	adjustment = incvalue;
-	adjustment *= delta;
-	adjustment = div_u64(adjustment, 1000000000);
+	adjustment = mul_u64_u64_div_u64(incvalue, (u64)delta,
+					 1000000ULL << 16);
 
 	incvalue = neg_adj ? (incvalue - adjustment) : (incvalue + adjustment);
 
@@ -257,7 +258,7 @@ static const struct ptp_clock_info e1000e_ptp_clock_info = {
 	.n_per_out	= 0,
 	.n_pins		= 0,
 	.pps		= 0,
-	.adjfreq	= e1000e_phc_adjfreq,
+	.adjfine	= e1000e_phc_adjfine,
 	.adjtime	= e1000e_phc_adjtime,
 	.gettimex64	= e1000e_phc_gettimex,
 	.settime64	= e1000e_phc_settime,
-- 
2.35.1.456.ga9c7032d4631

_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Intel-wired-lan] [net-next PATCH 4/7] i40e: use mul_u64_u64_div_u64 for PTP frequency calculation
  2022-07-21 21:29 [Intel-wired-lan] [net-next PATCH 0/7] intel: ptp: convert .adjfreq to .adjfine Jacob Keller
                   ` (3 preceding siblings ...)
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 3/7] e1000e: convert .adjfreq to .adjfine Jacob Keller
@ 2022-07-21 21:29 ` Jacob Keller
  2022-07-26 12:48   ` G, GurucharanX
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 5/7] i40e: convert .adjfreq to .adjfine Jacob Keller
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Jacob Keller @ 2022-07-21 21:29 UTC (permalink / raw)
  To: Intel Wired LAN

The i40e device has a different clock rate depending on the current link
speed. This requires using a different increment rate for the PTP clock
registers. For slower link speeds, the base increment value is larger.
Directly multiplying the larger increment value by the parts per billion
adjustment might overflow.

To avoid this, the i40e implementation defaults to using the lower
increment value and then multiplying the adjustment afterwards. This causes
a loss of precision for lower link speeds.

We can fix this by using mul_u64_u64_div_u64 instead of performing the
multiplications using standard C operations. On X86, this will use special
instructions that perform the multiplication and division with 128bit
intermediate values. For other architectures, the fallback implementation
will limit the loss of precision for large values. Small adjustments don't
overflow anyways and won't lose precision at all.

This allows first multiplying the base increment value and then performing
the adjustment calculation, since we no longer fear overflowing. It also
makes it easier to convert to the even more precise .adjfine implementation
in a following change.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_ptp.c | 17 ++++-------------
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
index 57a71fa17ed5..15de918abc41 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
@@ -353,25 +353,16 @@ static int i40e_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
 		ppb = -ppb;
 	}
 
-	freq = I40E_PTP_40GB_INCVAL;
-	freq *= ppb;
-	diff = div_u64(freq, 1000000000ULL);
+	smp_mb(); /* Force any pending update before accessing. */
+	freq = I40E_PTP_40GB_INCVAL * READ_ONCE(pf->ptp_adj_mult);
+	diff = mul_u64_u64_div_u64(freq, (u64)ppb,
+				   1000000000ULL);
 
 	if (neg_adj)
 		adj = I40E_PTP_40GB_INCVAL - diff;
 	else
 		adj = I40E_PTP_40GB_INCVAL + diff;
 
-	/* At some link speeds, the base incval is so large that directly
-	 * multiplying by ppb would result in arithmetic overflow even when
-	 * using a u64. Avoid this by instead calculating the new incval
-	 * always in terms of the 40GbE clock rate and then multiplying by the
-	 * link speed factor afterwards. This does result in slightly lower
-	 * precision at lower link speeds, but it is fairly minor.
-	 */
-	smp_mb(); /* Force any pending update before accessing. */
-	adj *= READ_ONCE(pf->ptp_adj_mult);
-
 	wr32(hw, I40E_PRTTSYN_INC_L, adj & 0xFFFFFFFF);
 	wr32(hw, I40E_PRTTSYN_INC_H, adj >> 32);
 
-- 
2.35.1.456.ga9c7032d4631

_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Intel-wired-lan] [net-next PATCH 5/7] i40e: convert .adjfreq to .adjfine
  2022-07-21 21:29 [Intel-wired-lan] [net-next PATCH 0/7] intel: ptp: convert .adjfreq to .adjfine Jacob Keller
                   ` (4 preceding siblings ...)
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 4/7] i40e: use mul_u64_u64_div_u64 for PTP frequency calculation Jacob Keller
@ 2022-07-21 21:29 ` Jacob Keller
  2022-07-27  8:18   ` G, GurucharanX
  2022-07-21 21:30 ` [Intel-wired-lan] [net-next PATCH 6/7] ixgbe: " Jacob Keller
  2022-07-21 21:30 ` [Intel-wired-lan] [net-next PATCH 7/7] igb: " Jacob Keller
  7 siblings, 1 reply; 16+ messages in thread
From: Jacob Keller @ 2022-07-21 21:29 UTC (permalink / raw)
  To: Intel Wired LAN

The i40e driver currently implements the .adjfreq handler for frequency
adjustments. This takes the adjustment parameter in parts per billion. The
PTP core supports .adjfine which provides an adjustment in scaled parts per
million. This has a higher resolution and can result in more precise
adjustments for small corrections.

Convert the existing .adjfreq implementation to the newer .adjfine
implementation. This is trivial since it just requires changing the divisor
from 1000000000ULL to (1000000ULL << 16) in the mul_u64_u64_div_u64 call.

This improves the precision of the adjustments and gets us one driver
closer to removing the old .adjfreq support from the kernel.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e_ptp.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
index 15de918abc41..2d3533f38d7b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
@@ -334,29 +334,31 @@ static void i40e_ptp_convert_to_hwtstamp(struct skb_shared_hwtstamps *hwtstamps,
 }
 
 /**
- * i40e_ptp_adjfreq - Adjust the PHC frequency
+ * i40e_ptp_adjfine - Adjust the PHC frequency
  * @ptp: The PTP clock structure
- * @ppb: Parts per billion adjustment from the base
+ * @scaled_ppm: Scaled parts per million adjustment from base
  *
- * Adjust the frequency of the PHC by the indicated parts per billion from the
- * base frequency.
+ * Adjust the frequency of the PHC by the indicated delta from the base
+ * frequency.
+ *
+ * Scaled parts per million is ppm with a 16 bit binary fractional field.
  **/
-static int i40e_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+static int i40e_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
 {
 	struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
 	struct i40e_hw *hw = &pf->hw;
 	u64 adj, freq, diff;
 	int neg_adj = 0;
 
-	if (ppb < 0) {
+	if (scaled_ppm < 0) {
 		neg_adj = 1;
-		ppb = -ppb;
+		scaled_ppm = -scaled_ppm;
 	}
 
 	smp_mb(); /* Force any pending update before accessing. */
 	freq = I40E_PTP_40GB_INCVAL * READ_ONCE(pf->ptp_adj_mult);
-	diff = mul_u64_u64_div_u64(freq, (u64)ppb,
-				   1000000000ULL);
+	diff = mul_u64_u64_div_u64(freq, (u64)scaled_ppm,
+				   1000000ULL << 16);
 
 	if (neg_adj)
 		adj = I40E_PTP_40GB_INCVAL - diff;
@@ -1392,7 +1394,7 @@ static long i40e_ptp_create_clock(struct i40e_pf *pf)
 		sizeof(pf->ptp_caps.name) - 1);
 	pf->ptp_caps.owner = THIS_MODULE;
 	pf->ptp_caps.max_adj = 999999999;
-	pf->ptp_caps.adjfreq = i40e_ptp_adjfreq;
+	pf->ptp_caps.adjfine = i40e_ptp_adjfine;
 	pf->ptp_caps.adjtime = i40e_ptp_adjtime;
 	pf->ptp_caps.gettimex64 = i40e_ptp_gettimex;
 	pf->ptp_caps.settime64 = i40e_ptp_settime;
-- 
2.35.1.456.ga9c7032d4631

_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Intel-wired-lan] [net-next PATCH 6/7] ixgbe: convert .adjfreq to .adjfine
  2022-07-21 21:29 [Intel-wired-lan] [net-next PATCH 0/7] intel: ptp: convert .adjfreq to .adjfine Jacob Keller
                   ` (5 preceding siblings ...)
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 5/7] i40e: convert .adjfreq to .adjfine Jacob Keller
@ 2022-07-21 21:30 ` Jacob Keller
  2022-07-28  9:51   ` G, GurucharanX
  2022-07-21 21:30 ` [Intel-wired-lan] [net-next PATCH 7/7] igb: " Jacob Keller
  7 siblings, 1 reply; 16+ messages in thread
From: Jacob Keller @ 2022-07-21 21:30 UTC (permalink / raw)
  To: Intel Wired LAN

Convert the ixgbe PTP frequency adjustment implementations from .adjfreq to
.adjfine. This allows using the scaled parts per million adjustment from
the PTP core and results in a more precise adjustment for small
corrections.

To avoid overflow, use mul_u64_u64_div_u64 to perform the calculation. On
X86 platforms, this will use instructions that perform the operations with
128bit intermediate values. For other architectures, the implementation
will limit the loss of precision as much as possible.

This change slightly improves the precision of frequency adjustments for
all ixgbe based devices, and gets us one driver closer to being able to
remove the older .adjfreq implementation from the kernel.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 73 +++++++++++---------
 1 file 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 ppb from the base frequency.
+ * Adjust the frequency of the ptp cycle counter by the
+ * indicated scaled_ppm 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;
-- 
2.35.1.456.ga9c7032d4631

_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Intel-wired-lan] [net-next PATCH 7/7] igb: convert .adjfreq to .adjfine
  2022-07-21 21:29 [Intel-wired-lan] [net-next PATCH 0/7] intel: ptp: convert .adjfreq to .adjfine Jacob Keller
                   ` (6 preceding siblings ...)
  2022-07-21 21:30 ` [Intel-wired-lan] [net-next PATCH 6/7] ixgbe: " Jacob Keller
@ 2022-07-21 21:30 ` Jacob Keller
  2022-07-28  9:52   ` G, GurucharanX
  7 siblings, 1 reply; 16+ messages in thread
From: Jacob Keller @ 2022-07-21 21:30 UTC (permalink / raw)
  To: Intel Wired LAN

The 82576 PTP implementation still uses .adjfreq instead of using the newer
.adjfine.

This implementation uses a pre-simplified calculation since the base
increment value for the 82576 is just 16 * 2^19. Converting this into
scaled_ppm is tricky, and makes the intent a bit less clear.

Simply convert to the normal flow of multiplying the base increment value
by the scaled_ppm and then dividing by 1000000ULL << 16. This can be
implemented using mul_u64_u64_div_u64 which can avoid the possible overflow
that might occur for large adjustments.

Use of .adjfine can improve the precision of small adjustments and gets us
one driver closer to removing the old implementation from the kernel
entirely.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
 drivers/net/ethernet/intel/igb/igb_ptp.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index 02fec948ce64..15e57460e19e 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -190,7 +190,7 @@ static void igb_ptp_systim_to_hwtstamp(struct igb_adapter *adapter,
 }
 
 /* PTP clock operations */
-static int igb_ptp_adjfreq_82576(struct ptp_clock_info *ptp, s32 ppb)
+static int igb_ptp_adjfine_82576(struct ptp_clock_info *ptp, long scaled_ppm)
 {
 	struct igb_adapter *igb = container_of(ptp, struct igb_adapter,
 					       ptp_caps);
@@ -199,15 +199,14 @@ static int igb_ptp_adjfreq_82576(struct ptp_clock_info *ptp, s32 ppb)
 	u64 rate;
 	u32 incvalue;
 
-	if (ppb < 0) {
+	if (scaled_ppm < 0) {
 		neg_adj = 1;
-		ppb = -ppb;
+		scaled_ppm = -scaled_ppm;
 	}
-	rate = ppb;
-	rate <<= 14;
-	rate = div_u64(rate, 1953125);
 
-	incvalue = 16 << IGB_82576_TSYNC_SHIFT;
+	incvalue = INCVALUE_82576;
+	rate = mul_u64_u64_div_u64(incvalue, (u64)scaled_ppm,
+				   1000000ULL << 16);
 
 	if (neg_adj)
 		incvalue -= rate;
@@ -1347,7 +1346,7 @@ void igb_ptp_init(struct igb_adapter *adapter)
 		adapter->ptp_caps.max_adj = 999999881;
 		adapter->ptp_caps.n_ext_ts = 0;
 		adapter->ptp_caps.pps = 0;
-		adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82576;
+		adapter->ptp_caps.adjfine = igb_ptp_adjfine_82576;
 		adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576;
 		adapter->ptp_caps.gettimex64 = igb_ptp_gettimex_82576;
 		adapter->ptp_caps.settime64 = igb_ptp_settime_82576;
-- 
2.35.1.456.ga9c7032d4631

_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [Intel-wired-lan] [net-next PATCH 2/7] e1000e: remove unnecessary range check in e1000e_phc_adjfreq
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 2/7] e1000e: remove unnecessary range check in e1000e_phc_adjfreq Jacob Keller
@ 2022-07-25  4:44   ` naamax.meir
  0 siblings, 0 replies; 16+ messages in thread
From: naamax.meir @ 2022-07-25  4:44 UTC (permalink / raw)
  To: Jacob Keller, Intel Wired LAN

On 7/22/2022 00:29, Jacob Keller wrote:
> The e1000e_phc_adjfreq function validates that the input delta is within
> the maximum range. This is already handled by the core PTP code and this is
> a duplicate and thus unnecessary check. It also complicates refactoring to
> use the newer .adjfine implementation, where the input is no longer
> specified in parts per billion. Remove the range validation check.
> 
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> ---
>   drivers/net/ethernet/intel/e1000e/ptp.c | 3 ---
>   1 file changed, 3 deletions(-)
Tested-by: Naama Meir <naamax.meir@linux.intel.com>
_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Intel-wired-lan] [net-next PATCH 3/7] e1000e: convert .adjfreq to .adjfine
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 3/7] e1000e: convert .adjfreq to .adjfine Jacob Keller
@ 2022-07-25 11:37   ` naamax.meir
  0 siblings, 0 replies; 16+ messages in thread
From: naamax.meir @ 2022-07-25 11:37 UTC (permalink / raw)
  To: Jacob Keller, Intel Wired LAN

On 7/22/2022 00:29, Jacob Keller wrote:
> The PTP implementation for the e1000e driver uses the older .adjfreq
> method. This method takes an adjustment in parts per billion. The newer
> .adjfine implementation uses scaled_ppm. The use of scaled_ppm allows for
> finer grained adjustments and is preferred over using the older
> implementation.
> 
> Make use of mul_u64_u64_div_u64 in order to handle possible overflow of the
> multiplication used to calculate the desired adjustment to the hardware
> increment value.
> 
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> ---
>   drivers/net/ethernet/intel/e1000e/e1000.h  |  2 +-
>   drivers/net/ethernet/intel/e1000e/netdev.c |  4 ++--
>   drivers/net/ethernet/intel/e1000e/ptp.c    | 15 ++++++++-------
>   3 files changed, 11 insertions(+), 10 deletions(-)
Tested-by: Naama Meir <naamax.meir@linux.intel.com>
_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Intel-wired-lan] [net-next PATCH 1/7] ice: implement adjfine with mul_u64_u64_div_u64
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 1/7] ice: implement adjfine with mul_u64_u64_div_u64 Jacob Keller
@ 2022-07-26 12:48   ` G, GurucharanX
  0 siblings, 0 replies; 16+ messages in thread
From: G, GurucharanX @ 2022-07-26 12:48 UTC (permalink / raw)
  To: Keller, Jacob E, Intel Wired LAN



> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of
> Jacob Keller
> Sent: Friday, July 22, 2022 3:00 AM
> To: Intel Wired LAN <intel-wired-lan@lists.osuosl.org>
> Subject: [Intel-wired-lan] [net-next PATCH 1/7] ice: implement adjfine with
> mul_u64_u64_div_u64
> 
> The PTP frequency adjustment code needs to determine an appropriate
> adjustment given an input scaled_ppm adjustment.
> 
> We calculate the adjustment to the register by multiplying the base
> (nominal) increment value by the scaled_ppm and then dividing by the
> scaled one million value.
> 
> For very large adjustments, this might overflow. To avoid this, both the
> scaled_ppm and divisor values are downshifted.
> 
> We can avoid that on X86 architectures by using mul_u64_u64_div_u64. This
> helper function will perform the multiplication and division with 128bit
> intermediate values. We know that scaled_ppm is never larger than the
> divisor so this operation will never result in an overflow.
> 
> This improves the accuracy of the calculations for large adjustment values on
> X86. It is likely an improvement on other architectures as well because the
> default implementation of mul_u64_u64_div_u64 is smarter than the original
> approach taken in the ice code.
> 
> Additionally, this implementation is easier to read, using fewer local variables
> and lines of code to implement.
> 
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> ---
>  drivers/net/ethernet/intel/ice/ice_ptp.c | 16 +++-------------
>  1 file changed, 3 insertions(+), 13 deletions(-)
> 

Tested-by: Gurucharan <gurucharanx.g@intel.com> (A Contingent worker at Intel)
_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Intel-wired-lan] [net-next PATCH 4/7] i40e: use mul_u64_u64_div_u64 for PTP frequency calculation
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 4/7] i40e: use mul_u64_u64_div_u64 for PTP frequency calculation Jacob Keller
@ 2022-07-26 12:48   ` G, GurucharanX
  0 siblings, 0 replies; 16+ messages in thread
From: G, GurucharanX @ 2022-07-26 12:48 UTC (permalink / raw)
  To: Keller, Jacob E, Intel Wired LAN



> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of
> Jacob Keller
> Sent: Friday, July 22, 2022 3:00 AM
> To: Intel Wired LAN <intel-wired-lan@lists.osuosl.org>
> Subject: [Intel-wired-lan] [net-next PATCH 4/7] i40e: use
> mul_u64_u64_div_u64 for PTP frequency calculation
> 
> The i40e device has a different clock rate depending on the current link
> speed. This requires using a different increment rate for the PTP clock
> registers. For slower link speeds, the base increment value is larger.
> Directly multiplying the larger increment value by the parts per billion
> adjustment might overflow.
> 
> To avoid this, the i40e implementation defaults to using the lower increment
> value and then multiplying the adjustment afterwards. This causes a loss of
> precision for lower link speeds.
> 
> We can fix this by using mul_u64_u64_div_u64 instead of performing the
> multiplications using standard C operations. On X86, this will use special
> instructions that perform the multiplication and division with 128bit
> intermediate values. For other architectures, the fallback implementation will
> limit the loss of precision for large values. Small adjustments don't overflow
> anyways and won't lose precision at all.
> 
> This allows first multiplying the base increment value and then performing
> the adjustment calculation, since we no longer fear overflowing. It also
> makes it easier to convert to the even more precise .adjfine implementation
> in a following change.
> 
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> ---
>  drivers/net/ethernet/intel/i40e/i40e_ptp.c | 17 ++++-------------
>  1 file changed, 4 insertions(+), 13 deletions(-)
> 

Tested-by: Gurucharan <gurucharanx.g@intel.com> (A Contingent worker at Intel)
_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Intel-wired-lan] [net-next PATCH 5/7] i40e: convert .adjfreq to .adjfine
  2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 5/7] i40e: convert .adjfreq to .adjfine Jacob Keller
@ 2022-07-27  8:18   ` G, GurucharanX
  0 siblings, 0 replies; 16+ messages in thread
From: G, GurucharanX @ 2022-07-27  8:18 UTC (permalink / raw)
  To: Keller, Jacob E, Intel Wired LAN



> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of
> Jacob Keller
> Sent: Friday, July 22, 2022 3:00 AM
> To: Intel Wired LAN <intel-wired-lan@lists.osuosl.org>
> Subject: [Intel-wired-lan] [net-next PATCH 5/7] i40e: convert .adjfreq to
> .adjfine
> 
> The i40e driver currently implements the .adjfreq handler for frequency
> adjustments. This takes the adjustment parameter in parts per billion. The
> PTP core supports .adjfine which provides an adjustment in scaled parts per
> million. This has a higher resolution and can result in more precise
> adjustments for small corrections.
> 
> Convert the existing .adjfreq implementation to the newer .adjfine
> implementation. This is trivial since it just requires changing the divisor from
> 1000000000ULL to (1000000ULL << 16) in the mul_u64_u64_div_u64 call.
> 
> This improves the precision of the adjustments and gets us one driver closer
> to removing the old .adjfreq support from the kernel.
> 
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> ---
>  drivers/net/ethernet/intel/i40e/i40e_ptp.c | 22 ++++++++++++----------
>  1 file changed, 12 insertions(+), 10 deletions(-)
> 

Tested-by: Gurucharan <gurucharanx.g@intel.com> (A Contingent worker at Intel)
_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Intel-wired-lan] [net-next PATCH 6/7] ixgbe: convert .adjfreq to .adjfine
  2022-07-21 21:30 ` [Intel-wired-lan] [net-next PATCH 6/7] ixgbe: " Jacob Keller
@ 2022-07-28  9:51   ` G, GurucharanX
  0 siblings, 0 replies; 16+ messages in thread
From: G, GurucharanX @ 2022-07-28  9:51 UTC (permalink / raw)
  To: Keller, Jacob E, Intel Wired LAN



> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of
> Jacob Keller
> Sent: Friday, July 22, 2022 3:00 AM
> To: Intel Wired LAN <intel-wired-lan@lists.osuosl.org>
> Subject: [Intel-wired-lan] [net-next PATCH 6/7] ixgbe: convert .adjfreq to
> .adjfine
> 
> Convert the ixgbe PTP frequency adjustment implementations from .adjfreq
> to .adjfine. This allows using the scaled parts per million adjustment from the
> PTP core and results in a more precise adjustment for small corrections.
> 
> To avoid overflow, use mul_u64_u64_div_u64 to perform the calculation. On
> X86 platforms, this will use instructions that perform the operations with
> 128bit intermediate values. For other architectures, the implementation will
> limit the loss of precision as much as possible.
> 
> This change slightly improves the precision of frequency adjustments for all
> ixgbe based devices, and gets us one driver closer to being able to remove
> the older .adjfreq implementation from the kernel.
> 
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> ---
>  drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 73 +++++++++++---------
>  1 file changed, 40 insertions(+), 33 deletions(-)
> 

Tested-by: Gurucharan <gurucharanx.g@intel.com> (A Contingent worker at Intel)
_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Intel-wired-lan] [net-next PATCH 7/7] igb: convert .adjfreq to .adjfine
  2022-07-21 21:30 ` [Intel-wired-lan] [net-next PATCH 7/7] igb: " Jacob Keller
@ 2022-07-28  9:52   ` G, GurucharanX
  0 siblings, 0 replies; 16+ messages in thread
From: G, GurucharanX @ 2022-07-28  9:52 UTC (permalink / raw)
  To: Keller, Jacob E, Intel Wired LAN



> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of
> Jacob Keller
> Sent: Friday, July 22, 2022 3:00 AM
> To: Intel Wired LAN <intel-wired-lan@lists.osuosl.org>
> Subject: [Intel-wired-lan] [net-next PATCH 7/7] igb: convert .adjfreq to
> .adjfine
> 
> The 82576 PTP implementation still uses .adjfreq instead of using the newer
> .adjfine.
> 
> This implementation uses a pre-simplified calculation since the base
> increment value for the 82576 is just 16 * 2^19. Converting this into
> scaled_ppm is tricky, and makes the intent a bit less clear.
> 
> Simply convert to the normal flow of multiplying the base increment value by
> the scaled_ppm and then dividing by 1000000ULL << 16. This can be
> implemented using mul_u64_u64_div_u64 which can avoid the possible
> overflow that might occur for large adjustments.
> 
> Use of .adjfine can improve the precision of small adjustments and gets us
> one driver closer to removing the old implementation from the kernel
> entirely.
> 
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> ---
>  drivers/net/ethernet/intel/igb/igb_ptp.c | 15 +++++++--------
>  1 file changed, 7 insertions(+), 8 deletions(-)
> 

Tested-by: Gurucharan <gurucharanx.g@intel.com> (A Contingent worker at Intel)
_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2022-07-28  9:52 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-21 21:29 [Intel-wired-lan] [net-next PATCH 0/7] intel: ptp: convert .adjfreq to .adjfine Jacob Keller
2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 1/7] ice: implement adjfine with mul_u64_u64_div_u64 Jacob Keller
2022-07-26 12:48   ` G, GurucharanX
2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 1/1] igb: convert .adjfreq to .adjfine Jacob Keller
2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 2/7] e1000e: remove unnecessary range check in e1000e_phc_adjfreq Jacob Keller
2022-07-25  4:44   ` naamax.meir
2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 3/7] e1000e: convert .adjfreq to .adjfine Jacob Keller
2022-07-25 11:37   ` naamax.meir
2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 4/7] i40e: use mul_u64_u64_div_u64 for PTP frequency calculation Jacob Keller
2022-07-26 12:48   ` G, GurucharanX
2022-07-21 21:29 ` [Intel-wired-lan] [net-next PATCH 5/7] i40e: convert .adjfreq to .adjfine Jacob Keller
2022-07-27  8:18   ` G, GurucharanX
2022-07-21 21:30 ` [Intel-wired-lan] [net-next PATCH 6/7] ixgbe: " Jacob Keller
2022-07-28  9:51   ` G, GurucharanX
2022-07-21 21:30 ` [Intel-wired-lan] [net-next PATCH 7/7] igb: " Jacob Keller
2022-07-28  9:52   ` G, GurucharanX

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.